home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-11-27 | 147.6 KB | 4,875 lines |
-
-
- PART 4
-
-
-
- - TUTORIAL 6.54 -
-
- Figure T6-62: Parallel Waves (PICTURE: T6-62)
-
- Play the animation and the method generates waves in "x" direction.
-
- 6.23.4 Waves and Ripples
-
- Of course, it is possible to create more than one WAVE method at the same
- level, in which case the generated waves will interfere with each other.
- In other words, the result wave is the sum of the component waves. Because
- the size of the parameters for wave methods defines the wave-length and
- -height, this feature can be used for example for generating "ripples" on
- waves.
-
- So, let's create two wave methods generating parallel waves perpendicular
- to each other.
-
- 1. Create parallel waves as described in the previous example.
-
- 2. Duplicate the method object, rotate it and make it much smaller.
-
- Figure T6-63: Interfering Waves (PICTURE: T6-63)
-
- Play the animation and there will be small waves in the big waves.
-
- 6.23.5 Waving Particles
-
- This example demonstrates how the wave method can be used for waving a
- set of primitives instead of a mesh.
-
- If the target object is not a freeform object, then it is treated as a
- "point" of a freeform object. Instead of using one freeform target for the
- method, we can use hundreds of primitives.
-
- So, let' s create an example where the wave method is applied to a number
- of spheres:
-
- 1. Create a line consisting of small spheres.
-
- 2. Create a WAVE method to the same level with the spheres.
-
- 3. Create a coordsys and a circle under the method.
-
- 4. Play the animation.
-
- - TUTORIAL 6.55 -
-
- Figure T6-64: Waving Particles (PICTURE: T6-64)
-
- - TUTORIAL 6.56 -
-
- Chapter 7 RPL
- -------------
-
- 7.1 INTRODUCTION
-
- RPL stands for REAL 3D Programming Language. It is a FORTH-like language
- integrated into the REAL 3D environment. It is a full featured programming
- language which provides you with power, flexibility and total control over
- all the features of REAL 3D.
-
- The language has three main uses: as a method for storing macros, as a
- file format for importing and exporting all the information needed to
- describe the scenes and animations you create, and as a programming
- interface to allow you to expand the functions of REAL 3D to fulfill any
- requirements you might have.
-
- Because RPL is meant to be used for expanding the REAL 3D program, it has
- been designed to be as fast in its execution as possible. It is also
- capable of making direct access to the Operating System. For these
- reasons, it is quite a low level language. However, considerable effort
- has been devoted to make it easy to learn with the intention of all users
- being able to make use of it.
-
- This section is intended to introduce you to RPL programming as easily as
- possible; but some understanding of basic computer programming principles
- has been assumed. If after reading through the introduction and working
- through the tutorial section you do not feel you have a full understanding
- of how to use RPL then there are many good books on introductory
- programming. Any that directly relate to FORTH will provide the best
- assistance, and most if not all the examples will work in RPL.
-
- 7.1.1 Basic Concepts
-
- First some RPL terminology to get started:
-
- Word
- A word is a collection of constants and references to previously defined
- words that are to be executed when the word is run; like a procedure or
- function in the languages "C" or Pascal.
-
- Vocabulary
- This is the collection of all defined words, variables and named
- constants.
-
- Stack
- This is an area of memory used by the RPL system for storing the
- information it needs to process the words you want to execute and the
- operands those words need for their execution.
-
- RPL, like FORTH, is a threaded language. Threaded languages grow
- incrementally; you define new words using existing words that are either
- predefined (standard RPL words) or words that you have defined earlier.
-
- RPL is interactive, it executes or compiles words the instant they are
- entered. New words become a part of the RPL vocabulary as soon as their
- definitions are completed. They can then be executed just by typing in
- their names and pressing <ENTER>, or they can be included in the
- definitions of new words. Words must be entered exactly as they appear in
- the vocabulary, upper-case letters must be upper-case and lower-case must
- be entered as lower-case. They must also be entered in full, they cannot
- be abbreviated in any way.
-
- - TUTORIAL 7.1 -
-
- 7.2 TUTORIAL
-
- 7.2.1 Getting Started
-
- To start your introduction to RPL the first step you must take is to open
- an RPL Window. Select PROJECT/Windows/RPL and a window very similar to an
- OS shell window will open. Through this window you will pass information
- to the RPL system and it can pass information back to you.
-
- To examine the interactive nature of RPL and for you to get started try
- the following simple examples. Remember to enter the words EXACTLY as
- they appear in the examples!
-
- Example 1: Print a number.
-
- Type the following text exactly as it is shown:
-
- 2.
-
- When you press <ENTER> RPL will respond:
-
- 2
-
- Note:
- You just asked RPL to print out the number "2". The character "." is a
- predefined command or word in RPL's vocabulary which prints out an integer
- value.
-
- Example 2: Print some text.
-
- Now enter the following line:
-
- "hello world" PUTS
-
- RPL responds:
-
- hello world
-
- Note:
- The word "PUTS" (Put String) is another predefined word which printed the
- text "hello world".
-
- Before you test any further examples some explanation of how RPL operates
- is necessary.
-
- 7.2.2 Stacks
-
- RPL is a stack oriented language. This means that RPL uses stacks to store
- operands, intermediate results and return addresses.
-
- RPL uses four stacks. The Parameter Stack holds arguments for RPL words as
- well as results after executing those words. The Return Stack holds
- addresses of locations from where other RPL words were called, so that
- program execution can return to the location from where the calls were
- made. The other two stacks are only used internally. The Control Stack is
- used to check that the structure of the word is correct and all flow
- control structures are balanced while compiling a new word. The Vocabulary
- Stack stores the references to the compiled words that form the RPL
- vocabulary.
-
- These stacks work in Last In First Out (LIFO) manner, which is explained
- below in "Parameter Stack".
-
- 7.2.3 Reverse Polish Notation
-
- RPL uses postfix-notation, also known as Reverse Polish Notation (RPN).
-
- In RPN the arguments, or operands, are pushed onto stack first and then an
- operation is applied to them. The result is left on top of the stack, and
- can be used in consecutive operations.
-
- The conversion from algebraic notation (the way you write mathematical
- expressions on paper) to RPN is quite natural.
-
- You start with the operands you would start with if you were doing the
- calculation manually, and then append an operator.
-
- Then you take other operands and apply other operations until all the
- operands and operations are used. That may sound difficult but a couple
- of examples should clarify the point.
-
- - TUTORIAL 7.2 -
-
- Example 3: Convert 12 + 5 + 2 to RPN.
-
- 1. Manually you would first add 5 to 12. Therefore you write:
-
- 12 5 +
-
- Remember, the operands come first and then
- the operator.
-
- 2. Then you would add 2 to the result of the previous addition.
-
- 2 +
-
- Note:
- Both "+" operators require two operands. The first addition uses 12 and 5
- but the second "+" seem to have only one operand, the number 2. The second
- addition takes the result of the first addition as its second operand.
- How the result of the first operation is preserved will be explained in
- the section about the Parameter Stack.
-
- So the whole expression in RPN is:
-
- 12 5 + 2 +
-
- 3. Finally you will use the "." word to print the result; so that the RPL
- text becomes:
-
- 12 5 + 2 + .
-
- And RPL responds by printing the result:
-
- 19
-
- Example 4: Convert 2 + 5 * 7 to RPN.
-
- 1. First you multiply 5 with 7 and then add 2 to the result.
- So in RPL you enter:
-
- 5 7 * 2 + .
-
- 7.2.4 Parameter Stack
-
- When RPL scans input, whether it comes from the keyboard or from a file,
- it uses the Parameter Stack to store all operands it detects. This will
- be just called "the stack" for brevity, when there's no risk of confusing
- it with the Return stack.
-
- There are three kinds of operands in the RPL system: integer , floating-
- point, and address. The address operands can be addresses of RPL words, or
- addresses of variables (integer or floating-point) or generic addresses,
- addresses to any kind of value you want. All the addresses are handled in
- the same way. That is to say that RPL makes no distinction between
- addresses of different types of items.
-
- The stack operates on the basis of the last operand in will be the first
- out. This is the LIFO principle as mentioned. If you picture the stack
- as a pile of bricks (or any other neatly stackable material), you put new
- bricks on the top of the pile and also take them off from the top.
-
- So how are operands put onto the stack? Just enter them, and they are
- "pushed" onto the stack so that the last entered number will be the top-
- most one. In Example 1, you pushed one operand onto the stack (number 2).
- Then the command "." pulled it off and printed it in your RPL window.
-
- Now push several operands onto the stack,
-
- Try the following:
-
- 1
- 2
- 3
-
- You pushed three numbers onto the stack. Print them all out by entering
- three "." commands and RPL responds:
-
- 3
- 2
- 1
-
- - TUTORIAL 7.3 -
-
- Try to enter "." command once more time and RPL will respond:
-
- STACK EMPTY
-
- There were no more operands left on the stack for RPL to print.
-
- You get the same error message if you, for whatever reason, try to pull a
- value from the stack when none are available. This would occur if you had
- two integers on the stack and entered the "+" word twice.
-
- The second "+" has only one stack item and the error message is given.
-
- Now examine what happened to the stack for Example 3. Diagrams will be
- used to illustrate what is happening with the stack as each step is
- interpreted.
-
- 1. Suppose you start with an empty stack.
-
- 2. The RPL statement "12 5 + 2 + ." was scanned by the RPL interpreter.
-
- 3. First, 12 was pushed to stack.
-
- +----+ <- top of stack
- | 12 |
- +----+
-
- 4. Then 5 was pushed on stack
-
- +----+<- top of stack
- | 5 |
- +----+
- | 12 |
- +----+
-
- 5. The "+" was scanned, which, because it is a executable word not an
- operand, is executed. The word "+" pops (takes off) the first two
- operands from the stack, then adds them and pushes the result back
- onto the stack.
-
- +----+
- | 17 |
- +----+
-
- 6. Then 2 was pushed on stack
-
- +----+
- | 2 |
- +----+
- | 17 |
- +----+
-
- 7. The last "+" was scanned, the top two stack items are added, resulting
- in the following stack situation:
-
- +----+
- | 19 |
- +----+
-
- 8. Finally the "." was scanned and interpreted and the value is printed
- leaving the stack in its initial empty state.
-
- Note:
- RPL words must be separated from each other and their operands by either
- a <SPACE> or <ENTER>, but using <ENTER> also passes the current line to
- the RPL system and it will be interpreted immediately. So the example
- above could also have been entered as:
-
- 12
- 5
- +
- 2
- +
- .
-
- 7.2.5 DataTypes
-
- There are three kinds of data types in the RPL system: integer, floating-
- point and string. These are often refered to as literals. In order to
- enter values on the operand stack, you type in literals separated by
- <SPACE> or <ENTER> just as you have done in the examples above.
-
- Integers can contain only integral values, such as -3, 0 and 12, while
- floating-point numbers can be used for representing decimal numbers like
- -1.2, 0.12 and 1243.1.
-
- - TUTORIAL 7.4 -
-
- 7.2.5.1 integers
-
- Integer literals begin with a optional sign (+ or -) and contain only
- decimal digits. So far you have only used integer arithmetic, with integer
- literals and their corresponding integer operator words.
-
- 7.2.5.2 Floating-points
-
- Floating-point literals are similar to integer literals but they contain
- a decimal point or a exponent separator or both. The exponent separator
- can be either "e" or "E". The exponant can then contain an optional sign.
-
- As you would expect, arithmetic operations can also be carried out with
- floating-point values. There are separate words to carry out these
- operations:
-
- F+ - add two floating-point values
- F- - subtract
- F* - multiply
- F/ - divide
- F. - print
- Fxx - etc.
-
- Example 5:
-
- Enter the following text:
-
- 100.0 0.5 F* F.
-
- RPL replies:
-
- 50.0000
-
- It did that because you pushed two floating-point values onto the stack
- then multiplied them as floating-points and finally printed out the
- return value from the "F*" word, as a floating-point.
-
- Example 6:
-
- Now try the following:
-
- 123
- F.
-
- and RPL responds with:
-
- 123.0000
-
- This demonstrates an important principle of RPL. RPL uses Object-
- Orientation Theory to handle the operands on the stack. This means that it
- knows the data type of each stack value and the data type it requires for
- each operand of a word and handles them accordingly. In Example 6 above,
- when the command "F." pulled the integer value 123 off the stack, it
- converted the value to the required type before it tried to use it.
-
- This also works if words requiring integer operands receive floating-point
- values.
-
- Example 7:
-
- When you enter:
-
- 6.8
- .
-
- RPL will respond with:
-
- 7
-
- The RPL word "." works with integers, it had to convert the floating-
- point value it pulled from the stack to an integer before it printed it;
- because integers cannot contain any fractional part the value was rounded
- to the nearest integer value.
-
- 7.2.5.3 STRINGS
-
- String literals begin and end with a double quote character. If a
- double-quote is wanted in a string literal, it should be preceded by a
- back-slash.
-
- - TUTORIAL 7.5 -
-
- For example:
-
- "This string contains a \"."
-
- Will be interpreted as:
-
- This string contains a ".
-
- If a back-slash is required then two must be entered consecutively.
-
- For example:
-
- "This string contains a \\."
-
- Will be interpreted as:
-
- This string contains a \.
-
- RPL handles strings slightly differently from the way the integers and
- floating-points are treated. With integer and floating-point literals
- the numerical value is pushed on stack, and with string literals the
- address of the first character of the string is placed on the stack.
-
- You have already encountered the string printing word "PUTS". Let's look
- at how it actually operates.
-
- Consider the RPL text:
-
- "Hello, this is a string" PUTS
-
- 1. When the string "Hello, this is a string" was typed, RPL did NOT push
- the entire string onto the stack. Instead the address of the string was
- pushed. The memory for the string itself was allocated from elsewhere.
-
- 2. The word "PUTS" then pulls the address out off the stack and copies the
- string from that address to the window. Every character has a
- corresponding value, which is used for representing the character, this
- is called the ASCII code. For example, the ASCII code for the character
- "!" is 33. So, when RPL stores the character "!", it actually stores
- the value 33. The RPL word "EMIT" can be used for printing out
- characters by supplying ASCII code for them as operands.
-
- Example 8:
-
- Enter the following:
-
- 33 EMIT
-
- and RPL replies:
-
- !
-
- So, you can store a simple string onto the stack and print it out using
- the EMIT function.
-
- Example 9:
-
- Enter:
-
- 76 80 82 EMIT EMIT EMIT
-
- and RPL replies:
-
- RPL
-
- Finally , you can investigate one property of string literals that might
- not be immediately obvious.
-
- As you just learned, entering a string caused RPL to allocate the memory
- for the string and push the address of it onto the stack. To be precise,
- the address of the first character is pushed onto the stack. This means
- that it is possible to use arithmetic operations to select part of a
- string.
-
- Example 10:
-
- 1. Type the following string:
-
- "Hello again!"
-
- - TUTORIAL 7.6 -
-
- Note:
- The first character of "again!" is the 6th in the whole string
-
- 2. Enter:
-
- 6 +
-
- Note:
- You have now added 6 to the address of the first character ("H") of the
- string.
-
- 3.Finally, type:
-
- PUTS
-
- and RPL replies
-
- again!
-
- Some care is needed when using this "address arithmetic"; if you make an
- error and change the address so that it is outside of the original string
- data structure, then the results are quite unpredictable. In the worst
- case you could crash the system if you read from certain hardware
- registers by mistake.
-
- 7.2.6 Stack Manipulation Words
-
- There are a number of words that change the order of the stack items. The
- "SWAP" word, as it's name implies, takes two values off the stack top and
- puts them back in reverse order.
-
- Example 11:
-
- 1 5 SWAP
-
- after 1 after 5 after SWAP
-
- +-------+-------+----------+
- | 1 | 5 | 1 |
- +-------+-------+----------+
- | 1 | 5 |
- +-------+----------+
-
- "SWAP" is only needed if the order of the operands affects the result. It
- is unnecessary when using words such as "+" and "*" among others.
-
- Quite often there is more than one way to enter an algebraic expression in
- RPL:
-
- Example 12: Calculate the value of
-
- 28 / (2 + 4 * 3)
-
- 1. You start from within the parentheses as you would when calculating
- manually:
-
- 4 3 * 2 + 28 SWAP /
-
- after 4 after 3 after * after 2
-
- +-------+-------+-------+-------+
- | 4 | 3 | 12 | 2 |
- +-------+-------+-------+-------+
- | 4 | | 12 |
- +-------+ +-------+
-
- after + after 28 after SWAP after /
- +-------+--------+----------+-------+
- | 14 | 28 | 14 | 2 |
- +-------+--------+----------+-------+
- | 14 | 28 |
- +--------+----------+
-
- 2. Or, start from the left:
-
- 28 2 4 3 * + /
-
- after 28 2 4 3 after * after + after /
- +--------------+-------+-------+-------+
- | 3 | 12 | 14 | 2 |
- +--------------+-------+-------+-------+
- | 4 | 2 | 28 |
- +--------------+-------+-------+
- | 2 | 28 |
- +--------------+-------+
- | 28 |
- +--------------+
-
- This illustrates that although you can usually manage without "SWAP", it
- can quite often make
-
- - TUTORIAL 7.7 -
-
- it easier to enter your expressions in an understandable way.
-
- The next useful word for manipulating the stack, is "DUP"; which, as its
- name suggests, duplicates the top stack value. This is useful when you
- need an entered value or intermediate result more than once.
-
- Example 13:
-
- Calculate
- (3 + 7 * 2) / 3 + (3 + 7 * 2) * 4.
-
- You can convert it to RPL and get:
-
- 3 7 2 * + 3/ 3 7 2 * + 4 * + .
-
- or you can use DUP and get
-
- 3 7 2 * + DUP 3 / SWAP 4 * + .
-
- You can try these out and see for yourself that they give the same result.
-
- To get a copy of the second stack item you use the word OVER.
-
- Example 14:
-
- To calculate 3 + 3 * 7 you can enter:
-
- 3 7 OVER * + .
-
- If you need get a copy of a value deeper in the stack you use the PICK
- word.
-
- Example 15:
-
- To get a copy of the fourth value on the stack you enter:
-
- 4 PICK
-
- Note:
- The count of stack items (i.e. 4) does not include the count itself
- although it will be on the stack top when "PICK" is applied. In the
- previous example 4 PICK will copy to the stack top the value which was the
- fourth stack item before 4 was entered.
-
- "ROT" rotates the three topmost stack values so that the third item will
- become the top item, and the first and the second item (counting from the
- stack top) will be the second and the third stack item respectively.
-
- Example 16: Push 3, 5 and 7 onto the stack and then apply ROT and see how
- it changes the stack.
-
- 3 5 7 ROT
-
- after 3 after 5 after 7 after ROT
- +-------+-------+-------+---------+
- | 3 | 5 | 7 | 3 |
- +-------+-------+-------+---------+
- | 3 | 5 | 7 |
- +-------+-------+---------+
- | 3 | 5 |
- +-------+---------+
-
- Note:
- You can use the .S" word toprint the contents of the whole stack without
- removing any values to see how this example progresses.
-
- The word ROLL is used to rotate a given number (n) of stack items so that
- the n'th stack item becomes the stack top item and all the items between
- the first and the n'th item are moved one position deeper in the stack.
-
- Finally there is also a word for popping a value off the stack without
- printing it. The word is "DROP". You will need it later when you examine
- conditional execution.
-
- - TUTORIAL 7.8 -
-
- 7.2.7 Compiling New Words
-
- The examples so far have only demonstrated that RPL can be used as a
- slightly peculiar calculator. If it is to be used as a programming
- language, RPL needs to be able to store a sequences of operations for
- repeated use or which need to be executed by another part of the program.
-
- Many programming languages call these sequences functions or subroutines.
- The term "word" from the FORTH programming language is adopted for RPL.
-
- A word is a collection of RPL code which can be recognised by its name.
- This code can consist of literals, references to variables and constants,
- and references to other words.
-
- A definition of a word begins with a colon ":" continues with the name of
- the new word, and ends with a semicolon ";".
-
- When the RPL interpreter scans the colon word, a new entry in the
- vocabulary is started. The name of the word and the type of entry (in
- this case a "word definition") are stored.
-
- Everything between the name and the ending semicolon is compiled as the
- word's definition. When a previously defined word is given as part of the
- definition, a reference to it is stored. When a literal is given, its type
- (integer, float or string) and its value are stored in the entry. When a
- named constant or a variable (See: Constants and Variables) is given, a
- reference to its own entry is stored. In summary, the vocabulary entry for
- a word is made of a name, the word type and a set of literal values and
- references to previously defined words,
-
- The following examples should help to explain:
-
- Example 17: Define a word that prints out a specific string.
-
- Enter:
-
- :Prompt
- "PROMPT TEXT>" PUTS
- ;
-
- Remember, there has to be at least one space between ":" and the name for
- the new word, because the ":" is itself a word.
-
- User-defined words are used just like any pre-defined word. To use them
- you just need to enter their name.
-
- Example 17b: Use the word "Prompt" defined above.
-
- Enter:
-
- Prompt
-
- RPL will print:
-
- PROMPT_TEXT>
-
- User defined words would be quite useless if you couldn't pass information
- to them to control their operation. However, as mentioned above, user-
- defined words are indistinguishable from the built-in words. This means
- that passing operands to them is carried out using the Parameter Stack in
- exactly the same way as you have passed operands to words since Example 1!
-
- Now test this by defining your own interger printing word.
-
- Example 18: New integer printing word.
-
- : MyPrint
- .
- ;
-
- - TUTORIAL 7.9 -
-
- Call it:
-
- 10 MyPrint
-
- and RPL responds:
-
- 10
-
- Or call it as follows:
-
- 10 20 100 MyPrint MyPrint MyPrint
-
- and the reply will be:
-
- 100 20 10
-
- Now create a function which prints numbers out twice. To do this, you have
- to use the "DUP" word mentioned previously.
-
- Example 19: Print number twice as an integer.
-
- : My2Print
- DUP
- .
- .
- ;
-
- Now call it:
-
- 10 My2Print
-
- and it will reply:
-
- 10 10
-
- or if you call it as follows:
-
- 10 My2Print 20 My2Print 100 My2Print
-
- RPL responds with:
-
- 10 10 20 20 100 100
-
- Before the final example in this section you should learn how to use
- "comments" so you can add notes to your program to inform others how it
- works (or remind yourself at a later date). The word "(" tells RPL to skip
- all following text up to the next ")" command or until the end of the
- current line. Because "(" is a word, you have to separate it from the text
- that follows with a space.
-
- Comment Examples:
-
- 1.
- ( this is a comment )
-
- 2.
- ( these are also
- ( legal comments
-
- 3.
- (this produces syntax error)
-
- 4.
- ( this is an illegal comment too )
-
- Finally create a function, which takes three numbers as an input and
- returns the integer average of them,
-
- Example 20: Calculate the average of three numbers.
-
- : MyAver
- ( add 3 numbers and divide result by 3 )
- + + 3/
- ;
-
- If you call it as follows:
-
- 10 20 30 MyAver .
-
- RPL returns:
-
- 20
-
- or try:
-
- 10 20 120 MyAver .
-
- and the response will be:
-
- 50
-
- - TUTORIAL 7.10 -
-
- 7.2.8 Constants and Variables
-
- RPL has a mechanism to store and fetch values not only from the stack but
- also in "constants" and "variables". A "constant" is a named entity whose
- value is set when it is defined, and the value can be referenced but not
- changed. A "variable" is a named entity whose value can be referenced and
- used for either input or output.
-
- Constants and variables must be defined outside word definitions. When a
- constant is defined, its value is taken from the stack top. When you later
- want to reference a constant you enter its name.
-
- 7.2.8.1 Constants
-
- Constants are used for storing values that won't change. Although this
- might seem to be the same as using literals, it is good programming
- practice to use constants instead of literal values. Constants should be
- descriptive, and this makes your code much easier to read by others as
- well as yourself. When a constant is referrenced by its name, the value
- is placed on the stack.
-
- Example 21 : Define integer constant "DaysInAWeek" with the value 7.
-
- Enter:
-
- 7 CONSTANT DayslnAWeek
-
- Then entering:
-
- DaysInAWeek .
-
- prints out:
-
- 7
-
- Example 22: Define the value for the floating-point constant "PI".
-
- 3.14159 FCONSTANT PI
-
- 7.2.8.2 Variables
-
- When a numeric variable is defined, its initial value is set to zero. For
- each numeric type (integer and floating-point) there are two words that
- are used to access this value.
-
- For integer variables these words are:
-
- @ (fetch) - takes the address of an integer variable and returns the value
- of that variable on the stack.
-
- ! (store) - takes two operands: the address of the integer variable and
- the new value for the variable, and changes the value of the variable.
- The address must be the top item on the stack and the new value the
- second.
-
- The address of a variable is pushed onto the stack when it is referred to,
- not the value as with constants.
-
- Example 23: Define integer variable COUNTER and store 17 into it, then
- check its value.
-
- VARIABLE counter
- 17 counter !
- counter @ .
-
- Examine what happened during this example step by step:
-
- "VARIABLE counter"
-
- 1. Space was reserved for one integer value, to be accessed by the name
- "counter".
-
- "17 counter !"
-
- 2. The number 17 was pushed onto the stack.
-
- - TUTORIAL 7.11 -
-
- 3. The address of the variable was fetched and pushed onto the stack.
-
- 4. The word "!" was executed, which takes the address of a variable off
- the stack and assigns the second operand to the value at that address.
- In a way, the name of a variable is the address of its value.
-
- "counter @ ."
-
- 5. The address of the "counter" variable was again pushed onto the stack.
-
- 6. The word "@" was executed, which moves the contents from the given
- address onto the stack.
-
- 7. The "." word was executed, which printed the value from the stack to
- your window.
-
- There are corresponding words for floating-point variables; which are
- "FVARIABLE", "F!" and "F@".
-
- Variables and constants can be used inside or outside of a word
- definition. When used inside a word definition, only a reference to the
- constant or variable is compiled in the word's dictionary entry.
-
- The value of the constant or the address of the variable is fetched only
- when the word is executed, not when it is defined.
-
- Although the stack is object oriented and can automatically convert
- between numeric types, the internal storage of integer and floating-
- point variables is different. This means that words that operate on
- floating-point variables, i.e. F! and F@ should not be used to access
- integer variables. The same applies to floating-point variables and the
- words for integer variable access (! and @).
-
- 7.2.9 Flow Control
-
- Every programming language has to be able to alter the program flow when
- certain conditions are met. It is also necessary to be able to repeatably
- execute a section of code. RPL has addressed these needs by including a
- versatile set of words into its basic vocabulary for controlling program
- flow. The flow control words can only be used from within word
- definitions.
-
- 7.2.10 Conditional Execution
-
- It is often necessary to decide whether a section of code should be
- executed or not. This is called conditional execution . The most basic
- conditional execution structure is "IF..ENDIF".
-
- The "IF" word takes the stack top value and uses it to make a decision
- about how the execution is to proceed; this decision value is called a
- "flag". In RPL a flag value is said to be "FALSE" if it is equal to zero
- and "TRUE" if it has any other value. If the flag is TRUE, the words
- between IF and the corresponding ENDIF are executed, otherwise execution
- skips to the word that is immediately after the ENDIF.
-
- 7.2.10.1 Comparisons
-
- To put a flag on the stack ready for IF, it is useful to use words that
- compare stack items and as a result push a flag on the stack. Built into
- RPL are the following comparison words:
-
- Integer Float
- ----------------------------
- = F= - is equal
- < F< - is less
- > F< - is greater
- >= F>= - greater or equal
- <= F<= - less or equal
- <> F<> - not equal
-
- Each of these takes two stack values, compares them, and places a flag
- onto the stack whose value depends upon the result of the comparison.
-
- - TUTORIAL 7.12 -
-
- Example 24: Compare 2 and 3 to see which is less.
-
- 2 3 <
-
- The second stack item is compared to the first stack item; the flag pushed
- on the stack indicates whether 2 is less than 3. A value of 1 means
- "TRUE", and a 0 means "FALSE".
-
- after 2 after 3 after <
- +-------+-------+-------+
- | 2 | 3 | 1 |
- +-------+-------+-------+
- | 2 |
- +-------+
-
- The flag states that two is less than three (as you may have guessed).
-
- 7.2.10.2 IF..ENDIF Structure
-
- This is the simplest form of conditional execution structure.
-
- Example 25: Unpredictable program execution
-
- : Maybe
- RANDOM 0.5 F<
- IF
- "Yes," PUTS
- ENDIF
- "Thats it" PUTS
- ;
-
- Try executing "Maybe" several times and examine its response.
-
- Note:
- This introduces the word "RANDOM" which returns a random floating-
- point number between 0.0 and 1.0 when executed.
-
- The previous example tests whether the return value from "RANDOM" is less
- than 0.5. If it is, it prints out the text "Yes, Thats it" otherwise it
- just prints "Thats it".
-
- This is the explanation of the previous example. When the "Maybe" is
- executed:
-
- 1. Executing "RANDOM" pushes a floating-point value onto the stack
-
- 2. 0.5 is pushed onto the stack
-
- 3. The "F<" word takes two (floating-point) operands, compares
- "random<0.5" and pushes the flag back onto the stack.
-
- 4. The "IF" function takes the flag off the stack and if it is non-zero,
- then the ""Yes," PUTS"" text is executed; otherwise execution skips to
- ""Thats it" PUTS"" after the "ENDIF".
-
- Note:
- That "IF" and "ENDIF" words must be contained within a word definition;
- also that every "IF" needs one corresponding "ENDIF".
-
- 7.2.10.3 IF..ELSE..ENDIF Structure
-
- Now you can define a word that prints only positive values, negative
- values are just disposed of.
-
- Example 26: Word to print only positive values.
-
- : .Pos
- DUP 0> ( compare operand to zero )
- IF
- . ( print it if greater )
- ENDIF
- ;
-
- If you enter:
-
- 4 .Pos
-
- RPL returns:
-
- 4
-
- So that seems to work.
-
- But what happens if you enter:
-
- - TUTORIAL 7.13 -
-
- -2 4 3 -1 .Pos .Pos .Pos .Pos
-
- It doesn't produce:
-
- 3 4
-
- but nothing at all. The problem is that the word does not get rid of the
- negative values, so you called .Pos four times with the same value of -1
- on the stack.
-
- You need to take some action if the value on the stack is not greater than
- zero. This is handled using an "ELSE" branch where the negative value will
- be dropped off the stack.
-
- Example 26b: Correct way to print only positive values.
-
- : .Pos
- DUP 0 >
- IF
- .
- ELSE
- DROP
- ENDIF
- ;
-
- This demonstrates another form of the IF structure, the IF. .ELSE..ENDIF
- structure.
-
- If you now enter
-
- -2 4 3 -1 .Pos .Pos .Pos .Pos
-
- you get
-
- 3 4
-
- as originally intended.
-
- 7.2.10.4 Inverting Flags
-
- As well as the integer and floating-point comparison words, there is one
- other useful word for use in conditional structures.The "NOT" word can
- be used for reversing the result of a comparison.
-
- For example:
-
- 1 0 20 <> .
-
- and:
-
- 10 20 = NOT .
-
- Both print out the same value of "1" because the condition is TRUE.
-
- 7.2.10.5 Nesting Conditionals
-
- Conditional structures can also be nested. This means that they can be
- stacked inside each other providing that for each "IF" of "IF..ELSE" there
- is a corresponding "ENDIF".
-
- Example 27: Use of nested IF..ELSE..ENDIF structure.
-
- : CheckIt
- DUP ( duplicate the operand so that you don't lose it
- 0 = ( compare it against to zero )
- IF
- "Zero" PUTS
- DROP ( dispose of duplicate because it won't be needed
- ELSE
- 0 > ( make comparison "is greater than" with duplicate
- IF
- "Greater" PUTS
- ELSE
- "Less " PUTS
- ENDIF
- ENDIF
- ;
-
- - TUTORIAL 7.14 -
-
-
-
-
- Now call it as follows:
-
- -2 CheckIt
- 3.7 CheckIt
- 0 CheckIt
-
- you should get the following response:
-
- Less
- Greater
- Zero
-
- 7.2.11 Loops
-
- In this section, the RPL words for branching back to repeat sections of
- code several times will be explained. This type of control structure is
- called a "loop". There are two basic kinds of loop: definite loops, which
- execute a specific number of times unless interupted, and indefinite
- loops, whose repeated execution is controlled conditionally in much the
- same way as the IF..ENDIF structure.
-
- 7.2.11.1 Definite Loops
-
- The basic RPL control structure for executing definite loops is
- "DO..LOOP". You specify beginning and ending values, called the limits,
- for a "loop variable". The ending value is first pushed onto the stack,
- then the beginning value, before the word "DO". Then you put the words to
- be repeated, and the structure ends with the word "LOOP".
-
- Example 28: Printing a string 1 00 times.
-
- : DoLoop
- 100 0 DO
- "RPL loops in style!" PUTS
- LOOP
- ;
- DoLoop
-
- The "loop variable", or index, starts with the starting value, and is
- incremented by 1 at the end of each iteration of the loop. When it reaches
- the ending value the loop is exited. There is a word for retrieving the
- value of the index. Its name is "I", and it should only be used between
- "DO" and "LOOP". It puts the current value of the loop variables on the
- stack.
-
- Example 29: Count up from 1 to 9 and print the index.
-
- : OneToNine
- 10 1 DO
- I.
- LOOP
- ;
-
- OneToNine
-
- Prints:
-
- 1 2 3 4 5 6 7 8 9
-
- The "DO..LOOP" always starts at a value and counts up by one until it
- reaches the ending value. If you want to increment the index by a value
- other than 1 , you can use another form of the definite loop: the
- "DO..+LOOP". The "+LOOP" word takes an operand from the stack and adds
- it to the index.
-
- If the ending value is greater than the beginning value, then the loop is
- exited if the loop variable becomes greater than or equal to the ending
- value.
-
- Example 30: Count from 0 to 1 0 in twos, printing the index.
-
- : UpInTwos
- 10 0 DO
- I.
- 2+LOOP
- ;
-
- UpInTwos
-
- Prints:
-
- 0 2 4 6 8
-
- - TUTORIAL 7.15 -
-
- If the ending value is less than the beginning value, then the
- "DO..+LOOP" is exited when the loop variable becomes less than or equal
- to the ending value.
-
- Example 31: Count down by one and print the index.
-
- : DownByOnes
- 10 0 DO
- I.
- -1 +LOOP
- ;
-
- 0 5 DownByOnes
-
- Prints:
-
- 5 4 3 2 1
-
- Note:
- In this example the word "DownByOnes" takes its operands from the stack,
- so you must supply them when you call the word.
-
- Both forms of the "DO" loop execute at least once since the conditional
- check is made when "LOOP" or "+LOOP" is executed. It is possible to
- terminate a definite loop prematurely. The execution of word "LEAVE"
- causes the loop to terminate at the next "LOOP" or "+LOOP".
-
- Example 32: Print the squares of numbers until the square > 50.
-
- : SquareLoop
- 10 0 DO
- I DUP * ( square index )
- DUP
- 50 > IF ( compare the square to 50 )
- DROP
- LEAVE
- ELSE
- .
- ENDIF
- LOOP
- ;
-
- When execute "SquareLoop" will print the squares of I until they exceed
- 50.
-
- 7.2.11.2 Indefinite Loops
-
- Unlike definite loops, an indefinite loop does not terminate after a
- specified number of iterations. It terminates when a condition is met,
- if ever.
-
- All indefinite loops, just like definite loops, must lie entirely within
- a single definition. The structure of the indefinite loops are:
-
- BEGIN..UNTIL
-
- BEGIN..WHILE..REPEAT
-
- BEGIN..AGAIN
-
- In each of these loops, "BEGIN" marks the beginning of the loop body,
- which extends to the terminating word "UNTIL" , "REPEAT", or "AGAIN".
-
- In the "BEGIN. .UNTIL" loop a flag is tested and removed from the stack at
- the end of each repetition of the loop. If the flag is TRUE, the loop
- terminates. Otherwise the loop repeats from the first word following
- "BEGIN". Since the test is made at the end of the loop, the loop will
- always be executed at least once.
-
- Example 33:
-
- : CountDown 1
- BEGIN
- DUP . ( print it out )
- 1 - ( decrement by one )
- DUP 0 <= ( if TRUE, terminate loop )
- UNTIL
- DROP
- "PANG" PUTS
- ;
-
- 10 CountDown1
-
- The "BEGIN..WHILE..REPEAT" form of indefinite loop first executes the
- code between "BEGIN" and "WHILE", and then a flag is tested, If the flag
- is TRUE, the words between "WHILE" and "REPEAT" are executed; then
- execution returns to "WHILE". If the flag is FALSE, then execution skips
- to after the "REPEAT".
-
- - TUTORIAL 7.16 -
-
- Example 34:
-
- : CountDown2
-
- BEGIN
- 1 - ( decrement by one )
- DUP ( if 0, terminates the loop )
- WHILE
- DUP .
- REPEAT
-
- "Bang" PUTS
- DROP
- ;
-
- 10 CountDown2
-
- The third form of indefinite loop has the form "BEGIN..AGAIN". Which
- executes forever unless either the word "QUIT" or "EXIT" is executed.
-
- "QUIT" terminates execution, empties all stacks and returns control to the
- interpreter, while "EXIT" exits the current word.
-
- Example 35:
-
- : CountDown3
- BEGIN
- DUP .
- 1 -
- DUP NOT
- IF
- EXIT
- ENDIF
- AGAIN
- ;
-
- 10 CountDown3
-
- 7.2.11.3 Nested Loops
-
- As with conditional structures, all the loop forms can be nested, In
- Examples 29 to 32 you used the RPL word "I" to obtain the value of the
- loop variable; when you nest "DO. .LOOP" structures the words "J" and "K"
- can be used to copy the indices of the second and third outer loops,
- respectively.
-
- Example 36: Print a multiplication table.
-
- ( print carriage return and line feed: )
- : CR 13 EMIT 10 EMIT .
-
- : multTable
- 6 1 DO
- 11 1 DO
- I J * ( multiply indices
- . ( and print the product
- LOOP
- CR
- LOOP
- ;
-
- multTable
-
- Will print:
-
- 1 2 3 4 5 6 7 8 9 10
- 2 4 6 8 10 12 14 16 18 20
- 3 6 9 12 15 18 21 24 27 30
- 4 8 12 16 20 24 28 32 36 40
- 5 10 15 20 25 30 35 40 45 50
-
- This looks a little untidy so you can tidy it up by adding a conditional
- to print a space.
-
- Example 36b: Print a neat multiplication table.
-
- : multTable
- 6 1
- DO
- 11 1
- DO
- I J * ( multiply indices
- DUP ( duplicate product for testing
- 10 <
- IF ( if<10 then print a space first
- "" PUTS
- . ( now print product
- ELSE ( two digits in product
- . ( so just print it
- ENDIF
- LOOP
- CR
- LOOP
- ;
-
- multTable
-
- - TUTORIAL 7.17 -
-
- Note:
- It is a convention to indent flow control structures as shown in the
- previous two examples. This does not make any difference to the RPL system
- but, like comments, makes your programs easier to read and understand.
-
- 7.2.12 Words and the Vocabulary
-
- The last example, as well as being your most comprehensive RPL program to
- date also demonstrates an important feature of the RPL language. If you
- define a word with the same name as a previously defined word then the
- latest definition is used.
-
- You can list the whole vocabulary of your current RPL window by entering
- the word "VLIST". Before you do this use the size gadget of the window to
- make it a decent size, the vocabulary is quite long.
-
- The whole vocabulary, including the built-in words, will be printed to the
- RPL window in chronological order with the latest words printed first. You
- should see that the last two words are both "mult_table".
-
- It is possible to remove word definitions from the vocabulary using the
- word "FORGET".
-
- Example 37 : Remove neat "multTable" from vocabulary.
-
- FORGET mult_table
-
- If you now execute "multTable" you will get the original untidy version.
-
- "FORGET" actually removes ALL the words after the specified word. So,
- assuming you have worked through all the examples, if you enter:
-
- FORGET Prompt
-
- Then all the words you have defined during this tutorial will be deleted.
- It is important to note that the RPL system makes NO DISTINCTION between
- the built-in words and words defined interactively or by loading a file
- (see next section). This means that if you create a word definition using
- the name of one of the built-in words then your new definition will
- replace the original. This can be quite significant if you replace an
- important or frequently used word.
-
- You can of course recover the situation using "FORGET"; which raises
- another important point: you can delete built-in words just as easily as
- your own. This makes it possible to create a situation where RPL does not
- have the vocabulary to do anything! Closing the window and opening a new
- one enables you to start with a fresh RPL environment.
-
- 7.2.13 Loading a File
-
- Entering RPL definitions directly to the window is acceptable for the
- short examples so far in this tutorial, but it is hard to recover from
- mistakes without having to completely re-enter a definition. Using a text
- editor you can write any RPL code to a file and then load that file into
- your RPL window.
-
- Example 38:
-
- Write the following RPL program using your favourite text editor and save
- it as "ram:test.rpl"
-
- "loading..." PUTS
-
- : CR
- 13 EMIT 10 EMIT
- ;
-
- : Hello
- "Hello world" PUTS CR
- ;
-
- "Done" CR
-
- - TUTORIAL 7.18 -
-
- Now type the following program:
-
- "ram:test.rpl" LOAD
-
- RPL responds:
-
- loading ... Done
-
- Now the words CR and Hello are defined and you can call them. Type:
-
- Hello
-
- and RPL responds
-
- Hello world
-
- 7.2.14 Using RPL windows
-
- You open a RPL window by selecting PROJECT/Windows/RPL. You can have many
- RPL windows if you want. RPL windows are similar to OS "Shell" windows.
- You can use <RAM>C and <RAM>V to cut and paste text to and from the
- "clipboard" and the cursor keys can be used to edit your text and even
- fetch previously entered text from the window "history" buffer.
-
- Each window is separate so that whatever words are defined in one window,
- cannot be used in other windows. Of course you can define identical words
- in different windows. The stacks are also specific to each window.
-
- It is possible though to use words defined in another window by
- establishing a parent-child link between two windows. This is done
- using the word INHERIT . The syntax for this word is:
-
- "name_of_RPL_window" INHERIT
-
- Example 39:
-
- 1. Define a word "HiThere" in your current RPL window
-
- : HiThere
- "Hi There" PUTS
- ;
-
- 2. Open a new RPL window and try to execute the word "HiThere":
-
- HiThere
-
- RPL responds
-
- HiThere ?
-
- because it didn't recognize the word.
-
- 3. Now enter the following line:
-
- "RPL" INHERIT
-
- 4. Try HiThere again and RPL responds "Hi There"
-
- From now on interactive commands, as well as new definitions entered in
- the "RPL.1" window search the vocabulary of "RPL.1", and then, if the word
- is not found, the vocabulary of "RPL". So if you have defined identical
- words in both windows the definition in "RPL.1" will take priority.
-
- Note:
- The INHERIT word actually takes an address as its operand, and this
- address points to the string containing the name of the RPL window whose
- vocabulary you wish to INHERIT Remember by entering the string between the
- double-quote marks its address was pushed onto the stack as an operand.
-
- - TUTORIAL 7.19 -
-
- 7.3 USING RPL FOR CUSTOMIZING EDITOR
-
- In this section we will show you how to use RPL to customize and expand
- the user interface and functionality of REAL 3D.
-
- The real power behind the customization is based on the fact that
- customization allows persons to develop working environments which suit
- as well as possible their different modelling needs, styles, and tools.
- Other people can take advantage of these additional tools etc developed
- by somebody else.
-
- 7.3.1 Communicating with RPL Programs
-
- Before we can go any further, let's take a look how RPL programs can
- interact with the user and vice versa.
-
- RPL contains sets of words which can be used for requesting information
- from the user.
-
- Open one View window and write the following program:
-
- : AreYouSure
- "YeslNo" "Are You Sure?" GET_ KEY
- IF
- "You are sure" PUTS
- ELSE
- "You are not sure" PUTS
- ENDIF
- ;
-
- AreYouSure
-
- When you call the word by typing its name, REAL 3D opens a requester with
- the header text "Are You Sure". Depending on which gadget you click RPL
- prints out either the text "You are sure" or "You are not sure". So, the
- word GET KEY takes two parameters: a string defining gadgets to be created
- and the header text for the requester. It returns a value corresponding
- to the selected gadget. Gadgets are separated with the character "l" and
- it is possible to create any number of them (well, there should be at
- least one).
-
- Write the following program:
-
- : GetKeyTest
- "FirstlSecondlThirdlCancel"
- "Select One of These" GET_KEY
- .
- ;
-
- Now call the word GetKeyTest several times and see what values it returns.
- The value corresponding to the rightmost gadget is always 0 (right
- selection is used for negative choice, hence the value 0). The value
- corresponding to the leftmost gadget corresponds to the value of 1 and is
- incremented gadget by gadget from left to right.
-
- The word GET STR can be used for requesting strings from the user, such as
- object names. It takes three parameters: the address of the buffer to hold
- the string, the maximum length for the string and the header text for the
- requester.
-
- Write the following program:
-
- 16 STRING ObjName
-
- : ObjCreate
- ObjName 1 5 "Create Object" GET _STR
- IF
- wOT_OR ObjName "CEND" C_LEVEL DROP
- ENDIF
- ;
-
- ObjCreate
-
- /*
- Get string from the user
- */
-
- - TUTORIAL 7.20 -
-
- This word opens a requester which allows you to enter the name for the
- object. If you select the gadget OK, the word creates a level object with
- the name you defined.
-
- The word GET_FLT allows you to request numerical data from the user. It
- takes two parameters: the address of the buffer (variable) to hold the
- defined value and a title for the requester.
-
- For example:
-
- FVARIABLE Length
-
- : GetLen
- Length "Define Length" GET_FLT
- IF
- Length F@ F.
- ENDIF
- ;
-
- GetLen
-
- This program asks user to define "Length" and prints it out.
-
- Its time to leave these "user interface" words now. There are also words
- available for requesting file names and vectors etc. These words can be
- used in a pretty similar way to those we have already discussed. Consult
- the "Reference Manual" whenever you need to use them.
-
- 7.3.2 "Master" ENVIRONMENT
-
- When R3D2 is first started one RPL environment is created. Unlike RPL
- windows this has no window associated with it.
-
- "Master" environment is responsible for taking care of the following
- things:
-
- 1. Processing of AREXX commands. All ARexx commands arriving to ARexx
- port of REAL 3D are directly passed to RPL interpreter.
-
- 2. Executing MACROS. For example, whenever you select the menu Project/
- Macros/Execute_Current, the following program is passed to Masters
- RPL environment:
-
- "t:macro.rpl" LOAD
-
- 3. Processing key bindings. When you press any key, that key with the
- prefix "KEY_" is passed to Masters RPL interpreter. For example, when
- you press the key "k", then the RPL word "KEY_k" attempts to execute.
- If such a word cannot be found, the display is flashed as an error
- indicator.
-
- 4. Processing RPL programs bound to icons in the Tool windows.
-
- 7.3.3 Binding Macros to Keys
-
- Any RPL program can be bound to any key by defining a word which has the
- same name as the key in question with the prefix KEY_. The word must be
- defined in Master's RPL Environment and it must return information with
- which windows should be refreshed. This return value consists of flags
- corresponding to each window type. Constants for these are defined in the
- file "editor.rpl".
-
- IWR_SELECT
- IWR_VIEW
- IWR_MAT
- IWR_ANIM
- IWR_COL
- IWR_ALL
-
- How to define words to "Masters" environment? There are three possible
- ways to do it:
-
- 1. Write a RPL program using any text editor, save it to a file and
- execute that file as a Macro.
-
- 2. Insert your RPL program to the file "s:rpl-startup".
-
- - TUTORIAL 7.21 -
-
- 3. Send your RPL program to ARexx port of REAL 3D.
-
- Let's write a simple RPL program and bind it to a key.
-
- 1. Add the following RPL program to the end of the file "s:rpl-startup".
-
- : KEY +
- 1 O_LOCK ( lock object data exclusively
- ( fetch selected objects on the stack:
- O_GETSEL
- 0.1 0 0 0 M_MOVE
- 0 O_LOCK (free lock
- IWR_VIEW ( only View must be refreshed
- ;
-
- 2. Start REAL 3D and create some objects.
-
- 3. Select one of the created objects and press the key "+". This causes
- "Master" to call your KEY + word which moves the selected objects to
- the positive direction of "x" axis.
-
- Of course this is very stupid thing to do. So, let's improve it by asking
- the user how much the selected objects should be moved.
-
- 1. Exit the Real and load s:rpl-startup file to your text editor.
-
- 2. Modify the KEY + word so that it looks like the following one:
-
- "vectors. rpl" LOAD
- VVARIABLE vMovement
-
- : KEY +
- vMovement "Move Selected Object"
- GET_VECT
- IF
- 1 O_LOCK
- O_GETSEL
- V@ vMovement 0 M_MOVE
- 0 O_LOCK
- ENDIF
- IWR_VIEW
- ;
-
- Now, start Real, create some objects, and press the key "+". REAL 3D opens
- a requester which allows you to enter three values defining how much to
- move selected objects. If you exit the requester with OK, all selected
- objects will be moved.
-
- Note:
- As a matter of fact, this is very handy macro because the requester allows
- you to define the formulas which are then automaticaly evaluated.
-
- 1. Press the key "+".
-
- 2. Type the following formula to the first gadget:
-
- 10*3.14/100
-
- and press the enter key. Your formula is evaluated and replaced with the
- result:
-
- 0.314
-
- 3. Click OK and the macro moves all selected objects 0.314 units along
- the "x" axis.
-
- One very powerful feature provided by REAL 3D is ability to open several
- screens. For example, you can use one HAM screen for rendering images and
- another four color hires screen for modelling. The following macro tries
- to bring the "Palette" window to the front, and if there are no Palette
- windows, it opens one. This kind of macro can be very useful when you have
- a lot of screens open.
-
- ( Bring window to front or )
- ( open it if it doesn't exist )
- : KEY_8
- 0 "Palette" iWM_ACTIVATE WND_SENDMSG
- IF
- iWT_PALETTE "Palette" 200 0 60 640
- WND_OPEN
- ENDIF
- 0
- ;
-
- - TUTORIAL 7.22 -
-
- When you press the key "8" the WND_SENDMSG word sends iWM_ACTIVATE message
- to all "Palette" windows. If none was found, it uses the word WND_OPEN to
- open one, This prevents you from accidentally opening more than one
- "Palette" window.
-
- The RPL "MENU" allows you to execute whatever menu through RPL. The word
- takes three parameters which describes the menu to be executed.
-
- For example, in order to execute the menu Create/Visible/Polygon enter the
- following string in any RPL window: 1 0 0 MENU
-
- then click the mouse on any View window and you can create a polygon. The
- reason for this is that the "Create" menu is the second menu. Because
- numbering starts from 0, the second menu corresponds the number 1.
-
- The second parameter (0) defines the first menu item of "Create", which is
- "Visibles". The last parameter (0) defines the first sub-menu, which is
- "Polygon".
-
- Naturally, you can create a word in to the rpl-startup file and call the
- MENU word to activate any menu. For example, by adding the following word
- to your rpl-startup file, you can activate the Lathe tool by pressing the
- key "l".
-
- : KEY_l
- 1 7 0 MENU ( Create/Compound_Tools/Lathe
- 0
- ;
-
- Note:
- If the menu is "Ghosted" you cannot execute it using the mouse or a word.
- Because the MENU word does the same as if you selected the actual menu,
- you don't have to worry about the return value.
-
- For example, the following key binding works only if the active window is
- a View window.
-
- : KEY_q
- 3 0 1 MENU ( View/Type/Perspective )
- 0
- ;
-
- The standard "rpl-startup" file contains a lot of examples of how to bind
- RPL programs to keys. Take a look at it for more examples and our attempt
- at a form of standardization.
-
- 7.3.4 Binding Macros to Icons
-
- REAL 3D allows you to create your own icons on Tool windows and bind RPL
- programs to them, When the icon is clicked, the corresponding RPL program
- is executed.
-
- There are two kind of bindings: RPL word bindings and RPL file bindings.
- In other words, the name of the icon can correspond either to the name of
- the RPL word or the name of the RPL file.
-
- In order to create an icon which is bound to a RPL word called HI THERE:
-
- 1. Write the program containing the word HI_THERE and save it as
- "Ram:test".
-
- : HI THERE
- "YeslNo" "Are You Sure" GET_KEY
- IF
- "You are Sure" PUTS
- ELSE
- "You are not sure" PUTS
- ENDIF
- 0
- ;
-
- 2. Select the function Project/Macros/Execute Named and execute the macro
- "Ram:test" (or insert it to your rpl-startup file and restart Real).
-
- 3. Open one Tool window.
-
- 4. Select the menu Tools/Create Icons which contains one string gadget and
- two radio-buttons. Enter the string HI THERE to the string gadget and
- make sure that the radio-button "Word" is selected. Click OK and one
- icon is created on the Tool window with the text HI_THERE.
-
- - TUTORIAL 7.23 -
-
- 5. Click the icon and your HI_THERE word is called causing Real to open a
- requester with the title "Are You Sure".
-
- In order to bind an icon to a file, just select the "File" radio-button
- for the icon to be created and then REAL 3D attempts to load the file
- whose name is the name of the gadget. REAL 3D tries to find that file from
- the directory defined by Settings/Paths.
-
- One very fast way to write a RPL program is to let the REAL 3D do it for
- you, in other words, to record a macro:
-
- 1. Create one sphere
-
- 2. Activate macro recording by selecting a menu Project/Macro/Record and
- move the sphere a bit to the right.
-
- 3. End macro.
-
- 4. Select the menu Project/Macro/Current_To_Named. REAL 3D opens a file
- requester and allows you to define a file name for the named macro.
- Type "ram:test".
-
- 5. Now create one icon on the Tool window with the name "test".
-
- 6. With the sphere selected, click the icon and your sphere is moved to
- the right.
-
- Note:
- REAL 3D standard configuration contains the directory named "r3d2:macros".
- If you put your macros there, the RPL interpreter can always find them.
- Now we have gone through some basic concepts how to customize REAL 3D by
- writing RPL procedures and binding them to keys and icons. This chapter
- only scratches the surface of possibilities for this customization ability
- which can offer users a good basis for learning new things and get new
- ideas about how to increase your productivity. The fact is that usually
- you have to spent a little time to build up a new function, but once you
- get it done, it can speed up your modelling in incredible ways.
-
- 7.4 CREATING ANIMATIONS USING RPL
-
- 7.4.1 Modifying Objects Directly
-
- The animation system of REAL 3D is very sophisticated. However, there
- might be some animations which cannot be created with it, simply because
- they are absolutely crazy. In this section, we will learn more about RPL
- by showing basic concepts about how to create these absolutely crazy
- animations which cannot be created in any other way.
-
- The principle is that we don't use the animation system of REAL 3D at all.
- Instead we will create animations by following the procedure described
- below:
-
- 1. Create your scene
-
- 2. Render it
-
- 3. Save the rendered image (if not rendered to a file)
-
- 4. Test if all frames are rendered, if they are, exit
-
- 5. Do something
-
- 6. Go back to the line 2.
-
- - TUTORIAL 7.24 -
-
- The line 5 (Do something) really means what it says. Because the RPL is a
- full featured programming language, there is not much you can't do with
- it.
-
- As a matter of fact, this is the way professional animators have created
- many of their really impressive animations.
-
- So, lets create an animation where the object just moves with a constant
- speed and direction. In order to do this, you need one View, one Select
- and one RPL window.
-
- Create one rectangle, select it and enter the following lines on your RPL
- window:
-
- O_GETSEL
- 0.1 0.2 0.0 0 M_MOVE
- REFRESH
-
- This program first fetches the addresses of selected objects on the stack,
- then moves the objects, and finally refreshes all windows.
-
- By the way, you can enter as many commands and operands in a single line
- as you wish (as long as their order is correct). For example, it is
- possible to enter the previous program as follows:
-
- O_GETSEL
- 0.1
- 0.2
- 0.0
- 0
- M_MOVE
- REFRESH
-
- or as follows:
-
- O_GETSEL 0.1 0.2 0.0 0 M_MOVE REFRESH
-
- As you can see, moving objects are not very difficult to create. However,
- they can be made even easier:
-
- Write the following function:
-
- : Up
- O_GETSEL
- 0 0.1 0 0 M_MOVE
- REFRESH
- ;
-
- Now, make sure that the rectangle is selected and enter the following
- command:
-
- Up
-
- RPL moves selected primitive up and refreshes your windows.
-
- Lets create another function which moves object down. It will look much
- like the first one.
-
- : Down
- 0 -0.1 0 0 M_MOVE
- REFRESH
- ;
-
- In order to move objects up and down several times enter:
-
- Up Down Up Down Up Down Up Down
-
- And all objects moved up and down several times.
-
- To make up and down stuff easier to carry out, enter the following
- function:
-
- : UpDown
- Up Down
- Up Down
- Up Down
- Up Down
- ;
-
- Type UpDown and you rectangle will move up and down several times. This
- way you can define useful functions and group them together.
-
- - TUTORIAL 7.25 -
-
- Now you know enough to create a simple animation. Create the following
- program:
-
- : AnimLeft
- 10 0 DO
- O_GETSEL
- -0.1 0 0 0 M_MOVE
- REFRESH
- LOOP
- ;
-
- Play it and you will see that it animates all selected objects by moving
- them to the left.
-
- : AnimRight
- 10 0 DO
- O_GETSEL
- 0.1 0 0 0 M_MOVE
- REFRESH
- LOOP
- ;
-
- Call this function and it moves your objects to the right.
-
- Lets create a function which moves objects first to the right, and then
- back to the left:
-
- : AnimRL
- AnimRight
- AnimLeft
- ;
-
- Call this function and you will see your objects moving as you expected.
-
- Then let's create an animation where objects this several times:
-
- : AnimRL10
- 10 0 DO
- AnimRL
- LOOP
- ;
-
- Call the "Anim10" and your objects goes back and forth ten times.
-
- Lets create a function, which allows you to define how many times to move
- forwards and backwards:
-
- : AnimN
- 0 DO
- AnimRL
- LOOP
- ;
-
- You didn't enter the upper limit for the DO function inside the "AnimM"
- function. So you have to pass it to the function when you call it.
- Call the "AnimN" as follows:
-
- 10 AnimN
-
- and it goes 10 times. Call it as follows:
-
- 20 AnimN
-
- and your objects goes 20 times.
-
- You can use the function "I" to get the current value of the "loop index"
- each time around. Let's consider the following:
-
- : LoopTest
- 5 -5 DO
- I.
- LOOP
- ;
-
- When you call this function, the result will be:
-
- -5 -4 -3 -2 -1 0 1 2 3 4
-
- You can use this index as a operand for something. For example, it can be
- used as a "frame counter" or parameter to trigonometric functions for
- defining nice motions.
-
- - TUTORIAL 7.26 -
-
- So, lets create an animation where all selected objects move along a sin
- curve:
-
- : SinMotion
- 100 0 DO
- O_GETSEL
- I 50 F/ ( x = I / 5 )
- I 10 F/ SIN F* ( y = sin 1/10 )
- 0 ( z=0 )
- 0
- M_MOVE
- REFRESH
- LOOP
- ;
-
- Call the word "SinMotion" and all selected objects will move along a sin
- curve to the positive direction of the "x" axis.
-
- Loops can be nested. Write the following program:
-
- : LoopLoop
- 10 0
- DO
- O_GETSEL -0.1 0 0 0 M_MOVE REFRESH
- 10 0
- DO
- O_GETSEL 0 0.2 0 0 M_MOVE REFRESH
- LOOP
- LOOP
- ;
-
- and call it. Selected objects move ten frames to the left, then one frame
- downwards and this cycle is repeated ten times.
-
- Sometimes a programmer wants to create a loop which terminates when some
- condition or event occurs. BEGIN UNTIL loop can be used for this purpose.
- It repeats until a condition is TRUE.
-
- : MyLoopTest
- BEGIN
- O_GETSEL 0.1 0.1 0 0 M_MOVE REFRESH
- RANDOM 0.9 F>
- UNTIL
- ;
-
- Previous function loops until the RANDOM function returns the value which
- is greater than 0.9. So the function UNTIL pushes one operand off the
- stack and if it is non zero, the loop is terminated.
-
- There are several other loops in RPL, but let's leave them for now. In the
- next section you will see how to use variables in RPL. A programming
- language is not a full featured programming language if it does not
- support variables. So, here you go!
-
- FVARIABLE t
-
- : Rotate
- 0 t F! ( t = 0 )
- BEGIN
- O_GETSEL
- t F@ SIN t F@ COS 0.0 0 M_MOVETO
- REFRESH
- t F@ 0.1 F+t F! ( t=t+0.1 )
- t F@ 3.14 F>
- UNTIL ( exit if t> 3.14 )
- ;
-
- Now call this function and it moves all the selected objects along a
- circular route with a radius of 1.
-
- Let's improve this function a bit so that it moves the selected objects
- along a circular path where the radius is passed to the function as a
- operand.
-
- FVARIABLE rad
-
- : Rot2 ( radius )
- rad F! ( store user defined radius to variable "rad" )
-
- 0 t F!
- BEGIN
- t F@ SIN rad F@ F* ( rad * sin t )
- t F@ COS rad F@ F* ( rad * cos t )
- 0.0 ( z = 0 )
- 0
- M_MOVETO
- REFRESH
- t F@ 0.1 F+ t F! (t=t+0.1 )
- t F@ 3.14 F> UNTIL ( exit if t > 3.14 )
- ;
-
- - TUTORIAL 7.27 -
-
- Call this function as follows:
-
- 0.1 Rot2
-
- and it will rotate all selected objects along the circular path with
- radius 0.1.
-
- Lets go through some lines of the previous function. The line
-
- t F@ SIN rad F@ F*
-
- does the following:
-
- 1. The address of the variable "t" is pushed onto the stack.
-
- 2. The function "F@" pulls the address of floating-point variable from
- the stack, fetches the value from that address and pushes the value
- onto the stack.
-
- 3. The function "SIN" takes one number off the stack and pushes the
- corresponding sin-value onto the stack.
-
- 4. The address of "rad" variable is fetched onto the stack
-
- 5. The function "F@" pushes the value from that address onto the stack
-
- 6. The function "F*" takes two numbers off the stack, multiplies them and
- pushes the result back onto the stack. Later this value is passed to
- function M_MOVE, which moves selected objects in x direction
- accordingly.
-
- Thats all for variables now. Just remember, when you type the name of any
- variable the pointer to the variable is returned onto the stack. If you
- type the string, the pointer to the string is returned onto the stack.
- So far we have created just wire frame animations. Lets create a complete
- ray traced animation:
-
- Write the following word:
-
- : RayTrace
- 10 0 DO ( ten frames )
- O_GETSEL
- 0.1 0 0 0 M_MOVE
- RENDER
- LOOP
- ;
-
- Now we use the word RENDER instead of REFRESH causing REAL 3D to use ray
- tracing instead of wire frame rendering. However, this animation does not
- yet save the rendered images. The word SCR_SAVE can be used for saving the
- screen containing rendered image.
-
- The following shows the complete program for creating an animation. Note
- that this example assumes that your View window is opened on REAL 3D
- custom screen whose name is "Real.1".
-
- 100 STRING FileName
-
- : RayTraceSave
- 10 0 DO
- RENDER
- I "Ram:test%d" FileName SPRINTF
- "Real.1" FileName SCR_SAVE
- O_GETSEL 0.1 0 0 0 M_MOVE
- LOOP
- ;
-
- The previous program uses the word SPRINT for building up the file names
- for rendered images so that the name of the first image is ram:test0
- and so on.
-
- The SCR_SAVE word takes two parameters: the name of the screen to be saved
- and the file name.
-
- - TUTORIAL 7.28 -
-
- Right, now we have created one complete animation. Although, it is very
- simple (objects just moved with constant speed along an "x" axis), it
- demonstrates the basic concepts needed for creating animations using this
- technique. However , there is one strange thing in this example: the
- result of the animation depends on the selected objects because we used
- the word O GETSEL to fetch the target objects for the M MOVE word.
- Although this might give your some good ideas, it is propably not what
- you wanted. So, lets create such an example where all cubes move to the
- right, and all rectangles move to the left. Create some cubes and
- rectangles and write the following program:
-
- 100 STRING FileName
-
- : RayTraceSave
- 10 0 DO
- RENDER
- I "Ram:test%d" FileName SPRINTF
- "Real.1" FileName SCR_SAVE
- "Root/cube*" O_FINDWILD 0.1 0 0 0
- M_MOVE
- "Root/rect*" O_FINDWILD -0.1 0 0 0
- M_MOVE
- LOOP
- ;
-
- Right, lets leave this section now and take a look at how to create
- animations using the actual Animation system of REAL 3D.
-
- 7.4.2 Creating New Methods
-
- In this section, we will demonstrate how to expand the animation system
- of the REAL 3D by writing new animation methods.
-
- As you already know, the animation system of REAL 3D is based on so
- called methods. A method is a procedure which can be associated with
- objects and which makes the object "intelligent enough to know what to
- do when the user plays with the time controlling gadgets.
- So, when do you have to create a new method?
-
- Only if there are no suitable methods available. It is so easy to create
- new animation methods, it is possible that somebody else has already
- created a method that solves your problem (Check the REAL 3D Support BBS
- for files 519-436-0140 Canada 1200 to 38400 Baud 24 hrs). Sometimes it is
- also possible to get the desired result by "customizing" existing methods.
- So, if there is no suitable method available and you cannot create such by
- customizing existing ones, then you probably have to write your own.
-
- Let's try it.
-
- 7.4.2.1 Do Nothing Method
-
- In this example we will learn how to create a new a method which actually
- does just nothing. The purpose of this kind of silly example is just to
- demonstrate the entire concept of how to attach procedures to objects in
- order to make them intelligent.
-
- So, start your favourite text editor program, type in the following RPL
- program and save it as RAM:test.rpl.
-
- :
- DoNothing
- 1
- ;
-
- & DoNothing "DO NOTHING" MTH_CREATE DROP
-
- Then select the menu Project/Macros/Execute Named and execute the file
- RAM:test.rpl. This installs the new method to the method list of Real.
-
- Select the menu Create/Structure/Method. Real opens a requester which
- allows you to define the type of the method to be created. The last method
- in the list should be DO NOTHING method. So, select it, click OK and you
- have just created one intelligent level object.
-
- Now create one target object for the method and play the animation. As
- you can see, it really does nothing.
-
- - TUTORIAL 7.29 -
-
- There is only one requirement for the object procedure: it must return
- either 1 or 0 (TRUE or FALSE). The return value 1 indicates that the
- method in question succeeded in its mission. The return value 0 indicates
- that something went wrong and the animation should be cancelled. Our
- procedure "DoNothing" always returns 1 because nothing really can go
- wrong.
-
- The last line of the program
-
- & DoNothing "DO_NOTHING" MTH_CREATE DROP
-
- then installs our method to the method list of Real. The MTH_CREATE takes
- two parameters: the address of the RPL word and the address of the name
- for the method. So, the first command "&" just pushes the address of the
- "DoNothing" word onto the stack.
-
- If the creation succeeded, the MTH_CREATE word returns the address of the
- created method. We are not interested in this adress so it is discarded
- with the word DROP.
-
- Because the DoNothing procedure is really stupid, it is easy to make it
- smarter.
-
- Add the following line to your "s: rpl-startup"
-
- "ram:test.rpl" LOAD
-
- This installs your method automatically when you start Real.
-
- Now modify the contents of the ram:test.rpl file so that the word
- DoNothing actually does something:
-
- : DoNothing
- "YeslNo" "Continue" GET_KEY
- ;
-
- Restart Real, create one DO_NOTHING method and play the animation.
- Requester is opened with the header text "Continue" and two gadgets "Yes"
- and "No". If you select "No" gadget, the GET_KEY returns 0 and the
- animation is terminated. If you select "Yes" gadget, the GET_KEY returns
- 1 and Real proceeds to the next frame asking you the same question again.
- Before we leave this DO_NOTHING example, let's do something useful. Let's
- create one real animation method which moves the target objects randomly.
- So, modify the "ram:test.rpl" file so that the DoNothing word looks like
- the following.
-
- : DoNothing
- 0 o2 @ RANDOM RANDOM RANDOM 0
- M_MOVETO
- 1
- ;
-
- Now, restart Real, create one DO_NOTHING method with some targets and play
- the animation. Now we have finally managed to get something which looks
- like an animation.
-
- The reason why we first showed these silly "do nothing" examples was that
- it is important to realize that it is totally up to the user to decide
- what his/her object procedures (methods) should do. They can be simple or
- complex and tailored to address specific needs of the user.
-
- 7.4.2.2 Move Absolutely Along a Path
-
- In this example, we will demonstrate how to create a method which moves
- target objects along a path so that if the target is dislocated from the
- path, it is immediately pulled back to it. This is very good example,
- because it demonstrates how powerful a tool RPL is and how user created
- methods expand the functionality of the program.
-
- The first thing to do is to decide what kind of properties our custom
- methods should have and what kind of parameteres it requires. In this
- case our method strongly resembles the PATH methods.
-
- So, the syntax diagram of the method looks like the following:
-
- +--------+
- | Parent |
- +--------+
- / \
- +--------+ +----------+
- | target | | Level(M) |
- +--------+ +----------+
- \
- +------+
- | Path |
- +------+
-
- - TUTORIAL 7.30 -
-
- Next we have to work out what the procedure to be created should do. In
- this case, it should do the following things:
-
- - Read the current time
-
- - Evaluate one point from the parameter object corresponding to the
- current time.
-
- - Move target object(s) to the evaluated point.
-
- So, when the time runs from 0 up to 1, the evaluated points move along the
- parameter object from its beginning point towards its end point
- accordingly pulling all target objects with it.
-
- The following program defines AbsPath method procedure and adds a new
- animation method to the Animation System.
-
- ( Load definitions for object data structure "objects. rpl" LOAD
-
- ( One general usage support word
- : GetTargets
- 0 ( 0 terminates the list
- o2 @ O_GETSUB ( first subobject
- BEGIN
- ( test if the object address is not zero
- DUP IF
- ( fetch the contents of wMETHOD field:
- DUP O.wMETHOD W@
- NOT IF ( if zero, valid target
- DUP
- ENDIF
- ELSE ( object address was zero, so
- EXIT ( no more targets, exit the word
- ENDIF
- ( fetch the address of the next object:
- O_GETNEXT
- AGAIN
- ;
-
- ( Actual object procedure
- : AbsPath
- GetTargets ( fetch target objects on the stack
- o1 @ O_GETSUB ( find the parameter object
- DUP NOT IF ( if no parameter, syntax error
- "Parameter Object Missing" PUTS
- 0 ( cancel animation
- EXIT ( exit word
- ENDIF
- t F@ u F@ v F@ O_EVAL 0
- M_MOVECOG
- 1 ( return 1, everything is okay
- ;
-
- ( Install new method to the animation system
- & AbsPath "ABS_PATH" MTH_CREATE DROP
-
- As you can see, it takes only some lines of RPL code to define a
- completely new animation method. After executing the program, one new
- method called ABS_PATH can be seen in the Create/Structure/Method
- requester.
-
- The word GetTargets is a general usage word which can be used by all your
- custom methods. It just fetches the addresses of all target objects on the
- stack and terminates the list with 0 as required by M_XXXX words.
-
- The variables "o1", "o2" and "t", "u", and "v" are automatically defined
- by the animation system. "o1" contains the address of the method object,
- "o2" contains the address of the parent object of method and t, u and v
- variables reflects the new time for the method.
-
- So, let's take a look at what the actual method procedure does.
-
- Whenever the time is changed, the animation system calls our procedure
- AbsPath.
-
- As already mentioned, the word:
-
- GetTargets
-
- just pushes the addresses of all target objects on the stack. Then the
- line
-
- o1 @ O_GETSUB
-
- - TUTORIAL 7.31 -
-
- fetches the address of the parameter object on the stack (parameter object
- is sub object of the method object).
-
- The code:
-
- DUP NOT IF
- "ERROR: Parameter Object Missing" PUTS
- 0 EXIT
- ENDIF
-
- then tests the return value of O_GETSUB and if 0, proper error message is
- printed out and 0 returned indicating that the method failed. The return
- value of 0 causes animation system to stop.
-
- Otherwise the code after ENDIF is executed:
-
- t F@ u F@ v F@ O_EVAL 0 M_MOVECOG
- 1
-
- which evaluates a point from the parameter curve and moves all targets to
- that point. Finally the value 1 is pushed on the stack, which indicates
- that method succeeded in its task.
-
- 7.4.2.3 Chain
-
- In this example, we will create a method which attempts to keep the
- distance between subsequent target objects constant. The distance between
- targets can be defined by associating a tag with the method object. If
- the tag does not exists, then our method uses default value, say 0.5.
- This method can be very powerful with some particle system oriented
- methods like radial force etc.
-
- Our methods should do the following things:
-
- 1. Find the tag value of "FDIS" tag associated with the method object.
-
- 2. Loop through all targets and move them so that the distance between
- COGs of subsequent targets equals the fetched tag value.
-
- Note:
- That we use vector operations here.
-
- Note:
- That this requires some basic knowledges of vector operations like how
- to add and subtract vectors.
-
- ( Useful support function Distribute
-
- FVARIABLE fLen
- VVARIABLE vTmp
-
- : Distribute ( 0 aObjects .... fDist )
- fLen F!
- iOP_COG O_PROP vTmp V!
- BEGIN
- DUP
- WHILE
- DUP iOP_COG O_PROP
- vTmp V@ VSUB VNORM
- fLen F@ VMUL
- vTmp V@ VSUB vTmp V!
- 0 SWAP vTmp V@ 0 M_MOVECOG
- REPEAT
- DROP
- ;
-
- ( Actual Object Procedure
-
- : OP_Chain
- GetTargets
- o1 @ "FDIS" O_FINDTAG DUP ( find tag FDIS
- IF ( if found, fetch its value on the stack:
- 4 + @ F@
- ELSE
- DROP 0.5 ( else push 0.5 on the stack
- ENDIF
- ( call distribute with objects and distance:
- Distribute
- 1
- ;
-
- & OP_Chain "CHAIN" MTH_CREATE DROP
-
- - TUTORIAL 7.32 -
-
- Again, we divided our method into two different words: Distribute and the
- actual object procedure OP_Chain. The reason for this is that
- "Distribute" is in general usage a useful word and it is a good
- programming practice to write modular programs by subdividing bigger tasks
- to smaller ones. For example, your can apply the "Distribute" now
- interactively to selected objects by defining just a core word which uses
- the GET_FLT and O_GETSEL words for fetching the required parameters for it
- instead of using O_FINTAG and GetTargets as we did here.
-
- The Distribute words take the following parameters:
-
- - object list terminated with 0
- - distance
-
- The first line
-
- fLen F!
-
- Just assigns the passed distance parameter to the variable "fLen". This
- makes it easy to use all over because we don't have to remember where
- it is in the stack.
-
- The next line starts the actual job:
-
- iOP_COG O_PROP vTmp V!
-
- O_PROP word is first used for fetching the COG of the first object on the
- stack and assigns it to the vector variable vTmp.
-
- Then in the beginning of the loop:
-
- DUP iOP_COG O_PROP
-
- fetches the COG of the second object on the stack.
-
- The line
-
- vTmp V@ VSUB VNORM
-
- fetches the COG of the first object on the stack, subtracts the COG of the
- second object from the COG of the first object and finally normalizes the
- result vector so that the lenght of it will be 1.
-
- The line
-
- fLen F@ VMUL
-
- then multiplies the unit vector by given distance. Now the length of the
- vector is given distance and it points from the second object towards the
- first one. Then we have to subtract it from the COG of the first object
- and we get the position for the second object. The following line
- subtracts the vector from the COG of the first object and saves the result
- back to the vTmp.
-
- vTmp V@ VSUB vTmp V!
-
- Then we just move the second target object to the defined point.
-
- 0 SWAP vTmp V@ 0 M_MOVECOG
-
- There is not much to tell about the actual object procedure OP Chain. It
- uses the word "GetTargets" to fetch the addresses of target objects on the
- stack, the distance to be used from the tag FDIS (or uses the value 0.5 if
- the tag does not exists) and then calls the word Distribute which does the
- actual job. Because the method cannot fail, it always returns 1.
-
- Before we leave this method example, let's take a look at how the
- Distribute word can be used interactively.
-
- 1. Open one RPL window and define the word Distribute.
-
- 2. Create 10 spheres resembling pearl necklace.
-
- 3. Write the following program:
-
- FVARIABLE fDistance
-
- : Distr
- fDistance "Define Distance" GET_FLT
- IF
- O_GETSEL fDistance f@ Distribute
- ENDIF
- ;
-
- 4. Select all spheres and call the word "Distr".
-
- - TUTORIAL 7.33 -
-
- 7. 4.2.4 Strange Force
-
- In this example we will create a method object which applies a very
- strange force field over targets causing the velocity and the spin of
- target objects to be changed . This is an absolutely crazy method, because
- the way we modify the velocity is absolutely random and it might be quite
- a difficult job to find such a force field in the real world. However, it
- demonstrates well the concept of designing new physical based methods and
- how to create and update object tags.
-
- First we need a word which defines a direction and the strength of the
- force field.
-
- : GetStrangeForce
- RANDOM RANDOM RANDOM
- ;
-
- Because we separate the word which defines the strength and direction for
- the force, it is very easy to change this method just by modifying this
- word.
-
- Then we need a word which attemps to read the value of velocity tag. If
- the VVEL tag does not exist, then it creates it. If the velocity tag
- exists, then the method modifies its value according to Newtons Laws of
- Motion. So, how much should the velocity of the object be changed if the
- force affects the object for "dt" seconds? According to Mr Newton, the
- strength of the force equals the mass of the object multiplied by the
- acceleration. Mathematically the problem can be solved as follows:
-
- F=ma => F=m*dv/dt => dv = F*dt/m
- -----------
-
- Because our force is not sensitive to the mass of the target object, we
- can forget the mass (m). Hence, the new velocity can be solved from the
- equation:
-
- dv = F*dt
- ---------
-
- The following word does all this:
-
- ( Word modifying the velocity )
- ( of a given object )
- : DoStrangeVEL ( aObj )
- "VVEL" O_FINDTAG DUP
- ( try to find VVEL tag
- IF ( if found:
- 4 + @ ( fetch the address of tag value
- DUP V@ ( fetch the velocity on the stack
- ( fetch the force vector on the stack:
- GetStrangeForce
- dt F@ VMUL ( dv = F* dt
- ( add "dv" vector to original velocity:
- VADD
- ( assign result back to the velocity tag:
- 4 ROLL V!
- ELSE
- DROP DUP "CEND" 0 0 0 "VVEL"
- O_CREATAG DROP
- ENDIF
- ;
-
- In order to get the new particle method perfect, also the spin must be
- affected somehow. The only difference between this and the DoStrangeSPI
- words is that the result vector for the VSPI tag is multiplied by 2*PI.
- This is because the spin is represented in radians and 2*PI radians
- corresponds to a full circle (360 deg).
-
- ( A word modifying the spin of the object )
- : DoStrangeSPI ( aObj )
- "VSPI" O_FINDTAG DUP
- IF
- 4 + @ DUP V@ ( original spin
- GetStrangeForce dt F@
- 2 PI F* F* VMUL ( delta
- VADD ( new spin
- 4 ROLL V ( assign result to VSPI
- ELSE
- DROP DUP "CEND" 0 0 0 "VSPI"
- O_CREATAG DROP
- ENDIF
- ;
-
- - TUTORIAL 7.34 -
-
- The actual object procedure then just scans through all targets and calls
- DoStrangeVEL and DoStrangeSPI words for each object.
-
- : OP StrangeForce
- GetTargets
- BEGIN
- DUP
- WHILE
- DUP
- DoStrangeVEL
- DoStrangeSPI
- REPEAT
- DROP
- 1
- ;
-
- & OP StrangeForce "STRANGE_FORCE" MTH_CREATE DROP
-
- 7.5 USING EVAL
-
- The EVAL word provides the user with an easy way to access data structures
- of Real, such as materials and objects. In this chapter we will show you
- some basic ways to use EVAL.
-
- Create one material with all properties set to default.
-
- How to set the brilliancy of the created material "mymat to 100? Type the
- following line:
-
- "data(mymat->spec)=100" EVAL DROP
-
- You just set the specularity of "mymat" to 100. To make sure that this
- really happened, open the material requester with the material and see.
-
- If you don't like Reverse Polish Notation, you can use eval to evaluate
- your formulas like this:
-
- "2*3+5" EVAL .
-
- which is the same as the phrase "2 3 * 5 + ." and RPL will reply:
-
- 11
-
- or like this:
-
- "2*3*sin(3*cos(123)+3)" EVAL F.
-
- or like this:
-
- "data(mymat->spec)=(data(mymat->bril)
- +data(mymat->tran))/2" EVAL.
-
- and RPL calculates an average of the brilliancy and transparency and
- assigns these results into a specularity field.
-
- So, let's create a material morphing animation. Create one sphere and add
- material "mymat" to it by creating one texture at the same level.
- Ensure that the rendering settings for the current View window are correct
- (don't use the Fast-mode because it ignores all material properties).
-
- Then write the following program:
-
- VARIABLE rg
-
- : MyAnim
- 10 0 DO ( ten frames )
- I 10 * rg! ( rg=I*10 )
- "data(mymat->roug)=rg" EVAL DROP
- RENDER
- LOOP
- ;
-
- and everything is ready for the show.
-
- Call the previous function and you'll see how the roughness of your
- rectangle is morphed during the animation.
-
- Right, how about objects. Assume that the full name (including the path)
- for you rectangle is "/Root/rectangle". Then you could print out the
- color of you rectangle as follows:
-
- "data(/Root/rectangle->R)" EVAL.
- "data(/Root/rectangle->G)" EVAL.
- "data(/Root/rectangle->B)" EVAL.
-
- - TUTORIAL 7.35 -
-
- or you can change the red signal of the color as follows:
-
- "data(/Root/rectangle->R)=120" EVAL.
-
- or you can print out the name of your object as follows:
-
- "data(/Root/rectangle->name)" EVAL PUTS
-
- or you can change the line pattern of your rectangle as follows:
-
- "data(/Root/rectangle->ptrn)=255" EVAL.
- REFRESH
-
- or you can change the register color for wire frame rendering:
-
- data(/Root/rectangle-> reg)= 3" EVAL.
- REFRESH
-
- For more about EVAL, see the reference manual.
-
- 7.6 OBJECTS
-
- In this section, we will demonstrate how RPL can be used for creating and
- manipulating objects.
-
- 7.6.1 Object Creation
-
- So, let's get started by creating a simple RPL program which just creates
- one primitive and renders it using default rendering settings.
-
- ( A minimal program for rendering a sphere
- 0.0 0.0 0.0 ( center )
- 0.5 0.0 0.0 ( a )
- 0.0 0.5 0.0 ( b )
- 0.0 0.0 0.5 ( c )
- 255 0 0 0 ( RGBA )
- "ellipsoid" ( name )
- 0 ( flags )
- "CEND" ( tags )
- C_ELLIPSOID DROP
-
- RENDER
-
- When passed to REAL 3D's stand-alone renderer, it should produce an image
- representing one red sphere.
-
- Lets go through what this program actually does.
-
- The first word C_ELLIPSOID creates an ellipsoid. The general form of all
- creation words is as follows:
-
- Geometry Color Attributes C_nnnn Address
-
- Geometric data is described first (in the example it consists of four
- vectors: center, a, b, and c). The form of geom. data depends on the
- type of the object to be created. Not all objects have geometric
- description. In this example, the geom. data defines a sphere, because
- the length of all three axes are the same.
-
- ( Geometric data for ellipsoid )
- 0.0 0.0 0.0 ( center )
- 0.5 0.0 0.0 ( a )
- 0.0 0.5 0.0 ( b )
- 0.0 0.0 0.5 ( c )
-
- The second data section is a color for the object. Color is defined by 32
- bits (RGB+A). Like geom. description, not all objects have color section.
-
- ( Color is defined by 32 bits R,G,B+A )
- 255 0 0 0 ( RGBA )
-
- The third data section defines so called "Attributes" for objects.
- Attributes can be divided into three different parts: name, flags and tag
- list. The name field defines a symbolic name for the object. This name can
- be used in many ways. For example, it can be used for finding the address
- of the object in order to create new objects, more on this later.
-
- The flags field is a 32 bit wide integer value. It is used for defining
- on/off kinds of attributes like whether or not this object should be
- "motion blurred" or "invisible". In the REAL 3D Editor, these flags can be
- defined using Modify/Properties/Attributes function. For more information
- about possible attribute flags, see the reference manual.
-
- - TUTORIAL 7.36 -
-
- The tag list can be used for defining custom attributes for objects needed
- by procedural textures, animation methods etc. The tag list consists of a
- number of tag identifier-value pairs. The tag value is a string whose
- length is four characters which identifies the value. The type of the tag
- value then depends on the tag identifier. The tag list is always
- terminated by "CEND" string.
-
- ( Attributes )
- "ellipsoid" ( name )
- 0 ( flags )
- "CEND" ( tags )
-
- C_ELLIPSOID creates an ellipsoid and returns the address. This address can
- be used in many ways as we will later see. In this example, it is not
- needed, so it is discarded by using the word DROP.
-
- The last word "RENDER" then asks REAL 3D to render the defined scene which
- in this example consists of only one sphere.
-
- One basic idea of RPL is that at the lowest level all data needed for
- defining objects must be passed to the RPL interface! There are no
- graphical environments used for defining parts of the data needed as in
- Renderman.
-
- However , this does not mean that in the case where a scene consists of a
- large number of almost identical objects the program would have to
- redefine the same data again for each object. Because RPL is a full
- featured programming language, there are many ways to solve this problem.
-
- For instance, let us imagine a scene consisting of 10 spheres. Would it
- take ten times more space to create such a scene as a scene which consists
- of only one sphere? Only if all the objects are totally different. Usually
- they are not, in which case identical data could be defined using, for
- example, a separate RPL word instead of redefining it for all primitives.
-
- Lets demonstrate this by creating an RPL program. The program would create
- two identical spheres to different position.
-
- ( A simple program implementing graphics )
- ( environment using different RPL words )
- : MY ELLIPSOID ( center addr )
- 0.5 0.0 0.0 ( a )
- 0.0 0.5 0.0 ( b )
- 0.0 0.0 0.5 ( c )
- 255 0 0 0 ( RGBA )
- "ellipsoid" ( name )
- 0 ( flags )
- "CEND" ( tags )
- C_ELLIPSOID
- ;
-
- 0 0 0 ( center )
- MY_ELLIPSOID DROP
-
- 1 0 0 ( center )
- MY_ELLIPSOID DROP
-
- RENDER
-
- To make this clear, let's create another program. The program creates a
- small "Renderman" style graphical environment used for defining
- "Attribute" data section for objects to be created.
-
- ( data for simple graphics environment )
- VARIABLE R
- VARIABLE G
- VARIABLE B
- VARIABLE FLAGS
- 16 STRING NAME
-
- ( words for manipulating )
- ( graphics environment )
- : RiName ( name - )
- NAME CPY
- ;
-
- : RiColor ( R G B - )
- B!G!R!
- ;
-
- : RiFlags ( Flags - )
- FLAGS !
- ;
-
- - TUTORIAL 7.37 -
-
- ( Ri style interface for creating )
- ( an ellipsoid )
- : RiEllipsoid ( center, a, b, c - )
- ( fetch color from graphics environment )
- R @ G @ B @ 0 ( A=0 )
- NAME ( fetch the address of the name )
- FLAGS @ ( fetch flags )
- "CEND" ( no tags )
- C_ELLIPSOID DROP
- ;
-
- ( create 3 blue spheres )
- 0 0 255 0 RiColor
- 0 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
- 1 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
- 2 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
-
- ( create 2 red ellipsoids )
- 255 0 0 RiColor
- 0 1 0 0.5 0 0 0 1 0 0 0 1 RiEllipsoid
- 0 2 0 0.5 0 0 0 1 0 0 0 1 RiEllipsoid
-
- ( create one green ellipsoid, "blue" )
- 0 255 0 RiColor
- "blue" RiName
- 0 -1 0 0.5 0 0 0.8 0 0 0 1.2 RiEllipsoid
-
- This listing defines a custom interface where geometric data is defined by
- the caller and the attributes are fetched from the graphics environment.
-
- 7.6.2 Object Instances
-
- RPL allows creation of "object instances". This is a useful feature
- whenever it takes less space to define geometric transformations and
- modify new objects out of existing ones than defining object data itself.
- The following example creates a number of spheres using this technique.
-
- FVARIABLE Rad
- VARIABLE Obj
- ( create first object )
- : MY SPHERE ( center rad - addr )
- Rad F! ( assign radius to variable "rad" )
- Rad F@ 0 0 ( a )
- 0 Rad F@ 0 ( b )
- 0 0 Rad F@ ( c )
- 255 0 0 0 ( RGBA )
- "ellipsoid" ( name )
- 0 ( flags )
- "CEND" ( tags )
- C_ELLIPSOID
- ;
-
- 0 0 0 0.5 MY_SPHERE Obj !
-
- ( create two object instances )
- ( from the first one )
- Obj @ M DUPLICATE 0 SWAP
- 1.5 0.2 0.2 0 M_MOVE
- ( the second one: )
- Obj @ M_DUPLICATE 0 SWAP
- 255 255 0 0 1 0 M_COLOR
-
- The word MY SPHERE takes two parameters which are center and radius and
- returns an address of the created sphere.
-
- The line
-
- 0 0 0 0.5 MY_SPHERE Obj !
-
- creates one sphere whose center is 0,0,0 and radius 0.5. The return value
- from the C_ELLIPSOID is not discarded using DROP but returned so that it
- can be stored into the variable "Obj".
-
- The last two lines contain the big idea so lets go through them line by
- line:
-
- Obj @ ( fetch the address of the sphere
- M_DUPLICATE ( duplicate it and leave
- ( its address on to the stack
-
- - TUTORIAL 7.38 -
-
- For the sake of efficiency, more than one object can be modified by RPL
- modify words at one call. The address 0 means that there are no more
- object addresses in the stack. So the following expression:
-
- 0 SWAP
-
- just terminates the object pointer list by 0.
-
- 1.5 0.2 0.2 0 M_MOVE
-
- then moves object instance 1 .5 along x axis and 0.2 along y and z axes.
- The second instance is created by changing the color of the sphere from
- red to yellow.
-
- 7.6.3 Grouping Objects Together
-
- Objects can be grouped together to create hierarchical object trees. This
- hierarchical construction of object conforms the basis for a large number
- of other features of RPL.
-
- The word C_LEVEL can be used for creating new levels into the object
- hierarchy and its syntax is as follows:
-
- Type Attributes C_LEVEL Addr
-
- The following example creates one simple object tree using the word
- MY_SPHERE created in the previous example. The structure of the tree to
- be represented is as follows:
-
- +------+
- | Root |
- +------+
- / \
- +--------+ +-----+
- | Sphere | | Sub |
- +--------+ +-----+
- / \
- +--------+ +--------+
- | Sphere | | Sphere |
- +--------+ +--------+
-
- The following program builds up the hierarchy.
-
- ( Creating a simple hierarchical object )
- wOT_OR "Root" 0 "CEND" C_LEVEL
- O_CURRENT DROP
-
- 0 0 0 0.5 MY_SPHERE DROP
- wOT OR "Sub" 0 "CEND" C_LEVEL
- O_CURRENT
-
- 0 0 0 0.5 MY_SPHERE DROP
- 0 0 0 0.5 MY_SPHERE DROP
-
- O_GETCURR O_GETPAR O_CURRENT
- DROP
-
- The first two lines
-
- wOT_OR "Root" 0 "CEND" C_LEVEL
- O_CURRENT DROP
-
- create one object of the type wOT_OR. The constant named "wOT_OR" is
- defined "objects.rpl" in file and the actual value of it is 2. By using
- constants makes the type of the level more easy to understand for human
- beings. It is strongly recommended to use these kind of definitions
- instead of direct values. The first parameter "wOT_OR" defines how volumes
- of all sub objects are interpreted. In this example, they are "OR" read
- with each other.
-
- The following fields
-
- "Root" 0 "CEND"
-
- defines attributes for the object and are identical with those we have
- already seen in previous examples.
-
- The word
-
- O_CURRENT
-
- takes one parameter, which is an address of an object and makes it the
- current level so that all latter objects will be created inside it. The
- word returns the address of the previous current level and we get rid of
- it using the DROP word.
-
- - TUTORIAL 7.39 -
-
- The creation of the second level is similar to the first one except for
- two things: the name of the level to be created is now "Sub" and we don't
- delete the return value from the O_CURRENT. We leave it on the stack so
- that we can use it later to pop back to the previous level using
-
- O_GETPAR and
- O_CURRENT words.
-
- O_GETPAR takes the address of an object and returns the address of its
- parent object. Then O_CURRENT makes it the new current level.
-
- Althought all previous words are pretty simple and clear, our example
- itself is not perhaps as clear as it could be. The reason for this is that
- it shows how to built up a hierarchy at the lowest level. Again, it is not
- necessary to define all parameters for C_LEVEL every time a new level is
- created. We can create our own core word, which takes only the name of the
- level to be created.
-
- In the following example we will create some useful words which reduce the
- size of the program and make it much more understandable.
-
- ( create level )
- : ObjBegin ( name )
- wOT_OR SWAP 0 "CEND" C_LEVEL
- O_CURRENT DROP
- ;
-
- ( close level )
- : ObjEnd
- O_GETCURR O_GETPAR O_CURRENT DROP
- ;
-
- "Root" ObjBegin
- 0 0 0 0.5 MY_SPHERE DROP
- "Sub" ObjBegin
- 0 0 0 0.5 MY_SPHERE DROP
- 0 0 0 0.5 MY_SPHERE DROP
- ObjEnd
- ( Now words ObjBegin and ObjEnd )
- ( can be used for defining hierarchy )
-
- It is very easy to close the hierarchy levels by leaving the return
- address of each created level on the stack and pull it out when it is
- needed. To get the parent object of it in order to pop up one hierarchy
- level. However, sometimes it is easier to build up the hierarchy first
- and then create the actual primitives. For example, let's build up a
- hierarchical tree which contains no primitives. The structure of the tree
- should be as follows:
-
- +------+
- | Root |
- +------+
- / | \
- / | \
- +------+ +------+ +------+
- | Sub1 | | Sub2 | | Sub3 |
- +------+ +------+ +------+
- / \
- / \
- +-------+ +-------+
- | Sub21 | | Sub22 |
- +-------+ +-------+
- / \
- / \
- +--------+ +--------+
- | Sub221 | | Sub222 |
- +--------+ +--------+
-
- Using the words ObjBegin/ObjEnd defined in previous example a program
- would look as follows:
-
- ( Building up an empty hierarchy )
- "Root" ObjBegin
- "Sub1" ObjBegin
- ObjEnd
- "Sub2" ObjBegin
- "Sub21" ObjBegin
- ObjEnd
- "Sub22" ObjBegin
- "Sub221 ObjBegin
- ObjEnd
- "Sub222 ObjBegin
- ObjEnd
- ObjEnd
- ObjEnd
-
- Because we discarded all addresses of created objects using the DROP word
- in the ObjBegin word, we don't remember any addresses of any objects. So,
- how do we create something inside the desired hierarchy level? The address
- of any object can be found by its name. For example, we could create a
- sphere inside the object named "sub222" as follows:
-
- - TUTORIAL 7.40 -
-
- ( find the address of object )
- "/Root/Sub2/Sub22/Sub221" O_FIND
- O_CURRENT DROP ( make it current )
- ( create one sphere )
- 0 0 0 0.5 MY_SPHERE DROP
-
- Another possibility is to use variables to store object addresses instead
- of fetching addresses using the O_FIND word.
-
- 7.6.4 SphereMan
-
- As a final example for this RPL tutorial, we will go through how to create
- "freeform objects" consisting of thousands of particles. For example, a
- body of the human being can be created using thousands of spheres
- distributed evenly over the body instead of using freeform meshes.
-
- This kind of task where we have to deal with thousands of objects would be
- almost impossible task to do without programming language.
-
- In this example we will use a SIMPLE SKELETON method to pull the sphere
- mass on the freeform mesh representing a head. RPL is used for creating
- all spheres as well as defining positions for each sphere so that they
- will be scattered all over the head.
-
- Clear the Settings/Creation/Auto_Index menu. This dramatically speeds up
- the creation process. It might be a good idea to switch the Undo feature
- off.
-
- Write the following program using your favourite text editor and save it:
-
- : CrSpheres ( iHowmany )
- 1 O_LOCK
- 0 DO
- 0 0 0 ( center )
- 0.05 0 0 ( a )
- 0 0.05 0 ( b )
- 0 0 0.05 ( c )
- 255 255 255 0 ( RGBA )
- "ell" ( name )
- 0 ( flags )
- "CEND"
- C_ELLIPSOID
- NOT IF
- "Not Enough Memory" PUTS
- 0 O_LOCK
- EXIT
- ENDIF
- I.
- LOOP
- 0 O_LOCK
- "Done" PUTS
- ;
-
- Now open one RPL window and load the program in. This just defines the
- word CrSpheres.
-
- As you can see the word CrSpheres takes one parameter which is the number
- of spheres to be created. Depending on the memory available, your can call
- this word with a different amount of spheres. If you have six megabytes of
- RAM memory installed, you should be able to create about 1000 spheres. So
- call the CrSphere as follows:
-
- 1000 CrSphere
-
- This creates 1000 spheres.
-
- Then we have to define the positions of the spheres on the skeleton mesh.
- If you are familiar with the skeleton methods, you know that the tag VPHS
- is used for defining at which position of the skeleton the target object
- in question is pulled. Because we are going to use a freeform mesh (a
- head) as a skeleton object, we have to define the first two components of
- the VPHS tag. For example, if the value 0,0 corresponds to the left top
- edge of the mesh, then the value 1,1 corresponds to the right bottom edge.
- The value 0.5 0.5 corresponds to the middle point of the mesh etc.
-
- - TUTORIAL 7.41 -
-
- So, write the following program (or just load it in from the rpl
- directory):
-
- ( A program scattering spheres evenly )
- ( over a skeleton mesh )
- VARIABLE iWidth
- VARIABLE iHeight
-
- : DefPhs ( aParent iWidth iHeight )
- iHeight!
- iWidth !
-
- O_GETSUB DUP NOT IF
- "No subobjects" PUTS
- EXIT
- ENDIF
-
- iHeight @ 0
- DO
- iWidth @ 0
- DO
- DUP "CEND" I iWidth @ F/J iHeight @
- F/ 0.0 "VPHS" O_CREATAG
- NOT IF
- "Cannot create tag" PUTS
- EXIT
- ENDIF
- "." PUTS
- O_GETNEXT DUP NOT IF
- "AII Done" PUTS
- EXIT
- ENDIF
- LOOP
- LOOP
- ;
-
- The word DefPhs takes three parameters: the address of the object
- containing all spheres, the number of spheres in "u" direction and the
- number of spheres in "v" direction. For example, if the Width parameter
- is 100, there will be 100 spheres in the "u" direction of the mesh.
-
- Now, make the object containing all created spheres the current level
- and enter the following command:
-
- O_GETCUR 35 35 DefPhs
-
- This defines the VPHS tag for each sphere in the current level so that
- each cross-section curve of the head will consist of 35 spheres.
-
- Create one SIMPLE SKELETON method beside all the spheres and add the
- following tag to it:
-
- ISKE 3
-
- This tells the skeleton method that the VPHS tags are already created and
- are up to date. If you forget to add this tag, the method will
- automatically define tags according to the current positions of the target
- objects.
-
- Load your freeform mesh representing a head inside the method object. Now
- the hierarchical structure of your object should be as follows:
-
- +------+
- | Root |
- +------+
- / \
- +--------+ +-------------+
- | o1..oN | | Skeleton(M) |
- +--------+ +-------------+
- \
- +---------------+
- | B-Spline_Head |
- +---------------+
-
- So, spheres (o1 ... oN) are pulled on the B-Spline_Head object by the
- skeleton method.
-
- Your "SphereMan" is now ready. Select the menu Animate/Control/Refresh and
- all the spheres are pulled on the head. Make the skeleton object invisible
- if you don't want to see the mesh itself.
-
- We will stop here, but you can carry on by animating the skeleton mesh.
- This also causes the spheres to be animated (because whatever you do to
- the head object, the spheres are always pulled on its surface). For
- example, you can add one WAVE method beside the B-Spline_Head and the
- sphere head will wave.
-
- +------+
- | Root |
- +------+
- / \
- +--------+ +-------------+
- | o1..oN | | Skeleton(M) |
- +--------+ +-------------+
- / \
- +---------------+ +---------+
- | B-Spline_Head | | Wave(M) |
- +---------------+ +---------+
- / \
- +------+ +-------+
- | axis | | curve |
- +------+ +-------+
-
- - TUTORIAL 7.42 -
-
- Now the spheres (o1 ... oN) are pulled on the B-Spline_Head which is
- morphed by the Wave method.
-
- Or you can use this technique just as a creation tool and delete the
- skeleton after all spheres are pulled on it. Then you can use the sphere
- as a beginning situation in particle animations.
-
- The possibilities are infinite and the only existing limit is your
- imagination.
-
- - TUTORIAL 7.43 -
-
- REFERENCE
- ---------
-
- Chapter 1 MENU FUNCTIONS
- ------------------------
-
- The following syntax is used to describe all the functions available
- by menu selection:
-
- / - SUB-MENU ITEMS FOLLOW
-
- * - TOGGLE GADGET
-
- 1.1 PROJECT
-
- The REAL 3D binary file format follows the IFF standard. The various
- data-structures necessary to define a complete REAL 3D project are each
- saved in a different data-section.
-
- Each data-structure can be saved and loaded independently. For each major
- data-structure type, there is a specific function. In addition, under the
- Project/ sub-menu are functions for loading and saving each individual
- section.
-
- There are two variants of loading for each data-section: "Insert" which
- loads the new data and adds it to the existing data-structure; and
- "Replace" which clears the existing data-structure if or when it loads
- the new data.
-
- The loader is intelligent, and can cope with loading files which contain
- some or all data-sections, but each loading function will only try to
- load those sections it is specified to load. The "Replace" variant of the
- loading functions do NOT clear the existing data-structure if the
- specified file does not contain the appropriate data-section.
-
- The different "Save" functions only save those sections they are specified
- to save.
-
- All the functions open a file-requester to allow the user to select the
- REAL 3D IFF file to load from. Changing the DOS path updates path-
- settings, so it is remembered by the requester the next time it is used.
-
- If "Confirm Save" gadget is set by using Settings/General requester, the
- user is asked to confirm the operation before the old file is overwritten.
-
- When working on a Workbench(TM) screen, Real-IFF files can also be loaded
- by moving their icons onto a View window.
-
- Objects/
-
- Insert
- Load new objects from specified file into the current level of hierarchy.
-
- Save
- Save selected objects to the specified file,
-
- Replace
- Clears the hierarchy if/when it loads the object section of the specified
- file.
-
- Project/
-
- The user is presented with a requester to define the new name for the root
- object.
-
- New
- This does the following:
-
- 1. Hierarchy cleared
- 2. Material Library deleted
- 3. Named Colors Library deleted
- 4. Grid Definitions removed
- 5. Vector stack is cleared
- 6. Undo Buffer cleared
- 7. Time and Frame Count are reset to zero
-
- - REFERENCE 1.1 -
-
- Insert
- Load all the available sections of a project definition from the specified
- file.
-
- Save
- Saves all sections of the current project definition to specified file.
-
- Replace
- Load all available sections from the IFF file and delete any corresponding
- data structures in memory.
-
- Insert Sections
- A requester is opened to allow only those sections of a REAL 3D file the
- user selects to be loaded. After the selection has been confirmed, the
- file requester will be opened.
-
- Save Sections
- Opens requester to select data sections for saving, then the file
- requester.
-
- Replace Sections
- Opens data sections requester for selecting the sections to replace from
- a file.
-
- Materials/
-
- Material definitions are stored in the material library. They are created
- and modified using a material window.
-
- Window
- Open a Material editor window. This allows materials to be created and
- modified while other actions, in particular rendering, are taking place.
-
- The material definitions are stored in a material data structure, called
- the material library, complete with their material name, The material
- definitions are created and modified using a material editor window.
-
- Figure R1-1: Material Editor Window (PICTURE: R1-1)
-
- - REFERENCE 1.2 -
-
- Local Menu:
-
- DEFINE/
-
- Texture <RAM>D
- Select name of image file using file requester.
-
- Show Texture <RAM>S
- Display image file. If the image is 24 bit and the External screen is
- open, then a requester will be produced asking for confirmation, as
- displaying the image may overwrite the contents of the External screen.
-
- Trans. Color <RAM>C
- Select Transparent color from current color.
-
- Tags<RAM>T
- Open the Tag requester to modify or define the tags associated with the
- current material.
-
- Gadgets of the Material window:
-
- Name
- Name of material in the Material library.
-
- Texture
- The path and name of an image file to use for defining various material
- properties like color or transparency. Each pixel in the bit-map relates
- to a point on the surface of the object, depending upon the type of
- mapping control object associated with the material and its position
- relative to the physical object, An index format string can be included
- as part of the name. This means that the value of the index variable "i"
- will be formatted to this specification and included as part of the file
- name.
-
- Spline
- When this gadget is set, and the target object for the material is a
- B-spline mesh, then the object itself is used for the mapping definition.
- Any coordinate transformations defined by mappings associated with the
- material are ignored. This means that the mapping of the texture file
- follows any modifications to the shape of the mesh.
-
- S-map uvwh
- These four numeric gadgets control the position and size of the image file
- when it is mapped onto a spline. The u and v values determine the position
- of the top left corner of the image and w and h control what proportion of
- the spline is covered. Each of these can be between 0.0 and 1,0,
-
- Color map
- Texture is to be used for material color definition.
-
- Bump map
- Red component of texture is used for bump map evaluation. The brighter the
- red component, the higher the bump.
-
- Transparency map
- Green component is used for transparency evaluation. The brighter the
- green component, the more transparent the material.
-
- Brilliance map
- Blue component is used for evaluating brilliance. The brighter the blue
- component, the more mirrorlike the material.
-
- Shadow map
- The RGB values of each pixel of the texture file are used to modify the
- current color values for the corresponding point of the objects surface,
- The modification formula is:
-
- R*r/255, G*g/255 & B*b/255
-
- Where: r, g, b are the color values of the pixel and R, G, B are the
- current color values of the surface point
-
- It is intended for this function to be used with grayscale texture files
- to artificially produce shadow effects as an alternative to using Render
- Settings/Normal mode or , when it is necessary, to create artificial
- shadows in addition to rendered ones.
-
- Note:
- If shadow mapping is used with a pure white object, it produces the same
- results as color mapping.
-
- - REFERENCE 1.3 -
-
- Clip map
- The surface of the object is clipped by the texture file. The object
- surface is removed wherever it is not covered by the texture file. This
- includes any areas not covered by the mapping or tiling, or any areas
- selected as transparent.
-
- Scope mask
- If this gadget is set, the material effect is modified by using the
- texture as a mask, which defines where the material is applied. Only the
- points which are affected by the texture, included in the material, get
- non-zero scope. The application test is equivalent to the one used for
- clip mapping.
-
- Transparent Color (Transp. col)
- The color to use as the transparent color is taken from the numeric
- gadgets: Trans.R, Trans.G, and Trans.B. This affects the application of a
- texture for clip mapping and scope mask. Transparent color is defined in
- 24-bit color space, so all values vary between 0 and 255. You can
- translate a color in original Amiga color system, values ranging from 0 to
- 15, to 24-bit system by multiplying each color component value by 16. For
- example, pure white R=15,G=15,B=15 corresponds R=240, G=240, B=240.
-
- Unshaded
- Light sources and shadows do not affect the shading of this material.
-
- Smooth
- Removes specular reflections on the boundaries of transparent materials.
-
- Exclusive
- When the rendering engine evaluates the material properties for each point
- on a surface, it mixes all the properties for each material defined by the
- mappings at the same hierarchical level. If only one mapping is present,
- then the material properties are mixed with the default material
- properties.
-
- Setting the Exclusive property means that other material definitions are
- ignored for any points on the surfaces covered by that specific material.
- See Also: "Effect" and "Scope" in this sub-chapter.
-
- Tiling Gadgets
-
- Tile
- Selects whether texture file is to be tiled in X, Y or both directions.
-
- Flip
- Selects whether tiled texture file is to be mirrored in X, Y or both
- directions. If set, then every second tile is flipped, making texture map
- edges match better.
-
- X-Freq. & Y-Freq.
- These numeric gadgets specify the number of tiling repetitions over the
- surface of the texture. If the frequency is set to 0, the texture is tiled
- infinitely for all mapping types, except spherical mapping. For parallel,
- both X & Y can be infinitely tiled; and for cylindrical and disk mapping,
- only Y = 0 is treated as infinite tiling. When infinite tiling is used,
- each tile is the size of the texture along that axis.
-
- Grade
- Selects whether color gradients are calculated for X, Y or both directions
- of the texture file. Color gradients produce smooth transitions from the
- color of one pixel to the color of the adjacent pixels.
-
- Specularity
- Controls how sharply defined are the high-lights reflected from the
- surface of the material by light sources. The higher the specularity, the
- smaller the high-light and the harder its edges.
-
- Specular brightness (Spec. bright.)
- This affects how intense the specular high-lights are.
-
- Brilliance
- The degree to which light is reflected directly from the material surface
- ("mirror-like" property),
-
- Transparency
- The degree to which light passes through the material surface.
-
- - REFERENCE 1.4 -
-
- Turbidity
- Controls the degree to which light is affected as it passes through the
- material. The higher the setting the denser the "fog".
-
- Turbidity saturation (Turbid. sat.)
- Defines how the distance which light travels in a turbid material affects
- the light. The default value 25 gives a linear result; so if the distance
- is doubled, then the effect is doubled. If this value is zero, then the
- distance has no effect at all. The actual equation is:
-
- "turbidity effect" = Turbidity *
- (distance^Turbid. sat.),
- ^ = to the power of
-
- Refraction
- This determines the degree to which light is bent as it passes through the
- material. It represents the speed of light in the material as a percentage
- of its maximum speed through empty space. The higher this value the less
- the light is bent.
-
- Roughness
- This controls the degree of "molecular texture" applied by the material.
- This "molecular" texture is a random bump-map which is independent of
- the magnification of the material.
-
- Dither
- This enables dithering of material color to be applied to individual
- objects and the precise amount of dithering to be selected. The actual
- amount of color deviation applied is given by:
-
- R = R + rnd,
- G = G + rnd,
- B = B + rnd where -di/2 < rnd < di/2
-
- where: di is the dither setting.
-
- Bump height
- Relative scale of bumps produced by bump-mapping texture file and
- procedural bump handler.
-
- Effect
- All materials at the same hierarchical level are mixed together. This
- controls how strongly the properties of the current material will affect
- the objects to which it is applied. Effect level is combined with the
- Scope material variable "s" to determine the final strength of the
- material properties at any point on the surface of the targets.
-
- APPLY
- Apply the current settings to the library under the name specified in the
- "Name" text-gadget. If a material under the name already exists, the old
- definition is overwritten. Otherwise a new material is created and
- appended to the material library.
-
- LOAD
- Open a requester to allow one of the materials in the current material
- library to be selected and loaded into the editor window.
-
- RESET
- Reset the material editor to display default material properties.
-
- Procedural Handlers
-
- In addition to being defined by a slider value or an IFF file, certain
- material properties can be defined using mathematical equations. These
- handlers are modifiers to the properties defined by the other settings.
-
- The equations to control these properties can come from several sources:
-
- Default
- No procedural handler.
-
- Formula
- An equation with an assignment to a system variable is entered in the
- expression box. This expression is evaluated using the RPL word EVAL.
-
- - REFERENCE 1.5 -
-
- RPL
- RPL text is used to define the handler. This can either take the form of
- direct RPL words and operands, or an external RPL file to be loaded.
- The RPL text is interpreted, so the fastest way to implement any handler
- is to define an RPL word which accesses the material variables directly.
- The name of this word is then entered into the expression box as the RPL
- text. The text is interpreted by the RPL "Master" environment, so if the
- word was defined in an RPL window, then it is necessary for "Master" to
- INHERIT the other environment. For more details of this see RPL
- documentation.
-
- Built-in Handlers
- Each procedural handler has several built-in formulas to produce
- particular effects more rapidly than using the equivalent as a Formula
- or RPL handler. These handlers use the a and b variables as control
- parameters for various aspects of their formulas. The default value for
- both a and b is usually 1.0, but Scope and Color/Waves are exceptions. For
- the Scope handlers, the default for a is Material Variable sz, the texture
- size, which is used if a = 0.0. In the Color/Waves handler, the default
- for b is 128.
-
- Descriptions
-
- The equivalent formula for each of these handlers are given under the
- heading for the handler type to which they apply. The formulas use w for
- the texture map width and h for texture map height, but these are not
- material variables.
-
- Material Variables
-
- a,b - User definable variables, initially assigned the value of the
- numeric gadgets to the right of the expression gadget.
- x - Horizontal texture coordinate. Type: FLOAT
- y - Vertical texture coordinate. Type: FLOAT
- z - Depth texture coordinate. Type: FLOAT
- sz - Size of texture geometry. Type: FLOAT
- r - Distance from the origin of the texture. Type: FLOAT
- s - Scope output variable. Type: FLOAT
- sp - specularity Type: FLOAT
- sb - specular brightness Type: FLOAT
- br - brilliance Type: FLOAT
- tr - transparency Type: FLOAT
- tu - turbidity Type: FLOAT
- ts - turbid saturation Type: FLOAT
- ri - refraction index Type: FLOAT
- ro - roughness Type: FLOAT
- di - dithering scale Type: FLOAT
- bh - bump height Type: FLOAT
- bx - Bump-map horizontal coefficient Type: FLOAT
- by - Bump-map vertiCal coefficient Type: FLOAT
- R - Red color component Type: INTEGER
- G - Green color component Type: INTEGER
- B - Blue color component Type: INTEGER
- t - Local animation time Type: FLOAT
- i - Material texture index Type: INTEGER
-
- - REFERENCE 1.6 -
-
- The following variables are available as a part of EVAL's function:
-
- Frm - Current Frame index Type: INTEGER
- Res - Frame Resolution Type: INTEGER
- T - Global animation time Type: FLOAT
-
- The ranges of x & y are either between 0,0 and 1,0 if no texture mapping
- type is being used, or between zero and the number of pixels along the x
- or y dimension of the texture file.
-
- z, sz & r are distances expressed in spatial coordinates and can have any
- positive value,
-
- If the mapping used is type Default, then x, y & z are the absolute
- spatial coordinates, and any mathematical handlers will effectively use
- Parallel mapping along z-axis.
-
- The value sz depends on the texture geometry in the following way:
-
- parallel - length of the shorter texture rectangle edge
- cylinder - radius of the cylinder (average if elliptic)
- sphere - radius of the sphere (average if elliptic)
- disk - radius of the disk (average if elliptic)
-
- The values for R,G & B are from 0 to 255. If a user defined formula
- assigns a value greater than 255, then it will be limited to 255.
- Negative values become zero.
-
- The range for T & t is between 0.0 and 1.0.
-
- The value of i is assigned by the user and can have any integer value.
-
- Frm & Res are a positive integer values between 0 and MAX_INT
-
- All the others should be between 0,0 and 100.0. If a formula takes a
- variable outside this range, then the effects are unpredictable.
-
- The order of the handlers indicates the order in which they are evaluated;
- Mapping first and Index last.
-
- Although the material variables can be assigned values at any time,
- assigning them values before the handler in which they are properly
- assessed has no practical effect, e.g. The color components are assigned
- their values from the texture file after the evaluation of the mapping and
- scope. The material variables x,y & z can be modified in any of the
- expressions,
-
- Handler Types:
-
- Mapping
-
- Material Variables: x, y & z.
-
- The Mapping handler is evaluated after the initial coordinate
- transformation calculations that use the mapping geometry have evaluated
- the values of x,y & z. Using an equation to modify one of these variables
- changes the way in which a texture file is mapped onto the surface.
-
- The following diagram shows how the mapping axes relate to the geometry
- of each mapping type. The x, y, z coordinates in the diagram relate
- directly to the material variables.
-
- - REFERENCE 1.7 -
-
- Figure R1-2: Mappings (PICTURE: R1-2)
-
- Built-in Handlers
-
- Tilt y = y + x*a*h/w
- Waves y = y + sin(x*a*PI/w)*b*h
- SwapXY tmp = x, x = y, y = tmp
-
- Scope
-
- Material Variables: s, sp, sb, br, tr, tu, ts, ro, ri
-
- The primary variable for the scope handler is "s" which, along with Effect
- level, determines how much of the material properties are mixed with the
- material properties already applied to the objects. If no other materials
- are applied, then the material is mixed with the default properties.
-
- Built-in Handlers
-
- Sphere if r < a s=100, else s=0
- InvLin s = 100/(1 + r^2/a)
- InvExp s = 100*exp(-r/a)
- Local s = max(100*a/(a-r),0)
- Temporal s = s*(a*(1 - T) + b*T)
-
- Where a = sz by default, except in Temporal, where a = 1 by default.
-
- Bump
-
- Material Variables: bh, bx & by.
-
- Bump-mapping is a process whereby the surface normal produced by the ray
- hit routines of the rendering engine are modified to make the surface
- appear to have "ripples" or "bumps". This modification is carried out by
- using vector addition between the true normal and two other vectors.
-
- The variables bx & by define the vectors used to deviate the normal and
- produce the bump-mapping effect. If a texture file is being used as a
- bump map, then bx and by are first evaluated from the red component of
- the texture.
-
- - REFERENCE 1.8 -
-
- The bump-mapping vectors and their relationship to the normal (denoted by
- n) are illustrated in the following diagram:
-
- Figure R1-3: Bump Variables in Mappings (PICTURE: R1-3)
-
- Built-in Handlers
-
- Waves bx = bx + sin(x*a*PI/w)*b
- Bumps bx = bx + sin(x*a*PI/w)*b, by = by + sin(y*a*PI/h)*b
-
- Color
-
- Material Variables: R, G & B.
-
- The color components of the material can also be mathematically modified.
- The initial values for R,G & B are evaluated from the texture file if
- used. Mathematical formulas can then be used to modify or replace these
- initial values, as with the other Material Variables. The size variable
- (sz) can be used for to bind a formula to the size of a texture.
-
- Built-in Handlers
-
- Bright R = R*b/(r*a + 1.0) ( G,B similar )
- Waves R = R + sin(x*a*w/h)*b ( G,B similar )
-
- Index
-
- Material Variable: i
-
- The material variable i is evaluated by any index format string used in
- the texture file name. Using a mathematical formula based upon either T, t
- or Frm makes it possible to control the indexes of texture files in very
- flexible ways to create moving material textures.
-
- Built-in Handlers
-
- Default i = a, a+1, ..., b-1, 0, 1, ..., b-1, ...
- PingPong i = a, a+1, ..., b-1, b-1, b-2, ..., 0, 1, ...
-
- Index handler default values are a = 0.0, b = 0.0 (zero offset and no
- modulo cycle).
-
- - REFERENCE 1.9 -
-
- Non-homogeneous Material Properties
-
- By using the procedural handlers, or mixing multiple materials, certain
- material properties can be evaluated non-uniformly, so the properties vary
- with their depth in the material. The number of times the material
- properties are sampled is dependent upon Render Settings/Mat. samples.
- The following properties, and their corresponding Material Variables are
- evaluated in this way:
-
- specularity
- specular brightness
- turbidity
- turbid saturation
-
- These non-homogeneous materials enable atmospheric gasses and sun-glow
- effects to be created.
-
- Delete
-
- Open a requester allowing the user to select a material from the library
- for deletion.
-
- If mappings still refer to deleted materials, then default material is
- used, If a new material with the same name is created or loaded, then the
- mappings will use the new definition.
-
- Delete All
-
- Delete all material definitions from the material library,
-
- Insert
-
- Load previously saved material definitions into material library.
-
- Save
-
- Save all material definitions in material library to the specified file.
-
- Replace
-
- Material library is cleared if the specified file contains a material
- section and new materials are loaded.
-
- Macros/
-
- Macros are files containing the ASCII text of the operands and RPL words
- which recreate the actions of the user. Hierarchical selection is not
- recorded, so the macro executes using the selected objects as operands.
- The current macro is saved in the file t:macro.rpl. Only those actions
- which modify objects or the hierarchy structure are recorded. As well as
- being executed by the functions below, macros can be executed from an RPL
- window using the "LOAD" word.
-
- The RPL system saves and executes macro files on a line by line basis.
- This means the only limit to the size of a macro is the OS maximum file
- size.
-
- * Record Macro
-
- Record all user selected functions and input data as the current macro.
- When macro recording is started, the previous current macro is deleted.
-
- Execute Current
-
- Execute current macro upon the selected objects. This is equivalent to
- executing the RPL command t:macro.rpl LOAD.
-
- Execute Named
-
- Produces file requester for user to select name of stored RPL text file.
- This is usually a macro, but it could be any executable file. The selected
- file is then executed in the "Master" RPL environment.
-
- - REFERENCE 1.10 -
-
- Repeat Current
-
- Execute current macro specified number of times. This is implemented
- internally using following RPL code:
-
- : Repeat_Current
- n 0 DO
- t:macro.rpl LOAD
- LOOP
- ;
-
- where n is the number of repetitions requested by the user.
-
- Spread Current
-
- Executes the current macro upon selected objects increasing execution
- count by one for each consecutive object. The execution count starts from
- zero, so it is not executed at all for the first object, then once for
- the second and twice for the third.
-
- Current to Named
-
- Opens a File Requester to the Macro Directory allowing user to define a
- new name for the current macro. This does not affect the operation of the
- current macro. This is the equivalent to copying the macro file using the
- OS.
-
- Named to Current
-
- Opens file requester allowing the user to select the macro file to be
- copied to the current macro file. This can also be accomplished using OS
- file copying.
-
- Named Colors/
-
- Named colors are a way of storing special colors which need to be used
- repeatedly and on different projects. The color values of these colors are
- saved in a library which can be saved to a file, then re-loaded at a later
- date.
-
- Select
-
- A color is selected from the named colors library using a requester. The
- value of the current color will assume the value of the named color
- selected.
-
- Create
-
- The RGB values of the current color are saved in the named colors library
- under the name specified.
-
- Modify
-
- A named-color is selected from the library and its RGB values are changed
- to those of the current color.
-
- Delete
- The selected color is deleted from the library.
-
- Insert
-
- Load the file specified into the Named colors library. The existing named
- colors are not replaced.
-
- Save
-
- Save the Named colors library as the file specified,
-
- - REFERENCE 1.11 -
-
- Replace
-
- Replace the Named colors library if the file specified contains
- appropriate data section.
-
- Windows/
-
- Most windows are opened on the default public screen unless they are too
- large, when they will be opened on another public screen which is large
- enough. The animation window and palette window each open on their own
- private screens, which take their Interlace/Non-Interlace properties from
- the default public screen.
-
- Select
-
- Open window for selecting objects and moving through the hierarchy.
- Clicking on individual names selects a single object. Using <DRAG> over
- the Select window multi-selects objects. To de-select objects use
- <LMB><SHIFT> or <DRAG><SHIFT>.
-
- The Select window uses the following text styles to indicate which types
- of objects are in the hierarchy:
-
- - Normal style used for primitives.
- - Bold style used for levels.
- - Italic used for controls and mappings.
-
- The current level is shown at the top left of the select window. All the
- objects in that level are indented and arranged in their order in the
- hierarchy from first to last.
-
- - Methods are shown with "(M)" after their name, unless they are the
- current level, when their method type will be shown in full.
- - A level with the boolean operator "AND" is shown with "(A)" after its
- name.
- - In addition to being printed in italics, mappings have "(T)" as a
- postfix to their name.
-
- The purpose of the select window is to show the logical structure of the
- object and to make it possible to point objects through their names.
-
- View
-
- Open a general purpose View which is the window into the REAL 3D universe.
- Individual Views can be configured using the functions in the View menu.
- Each View stores all its own settings, including both the sizes and
- positions selectable with the "zoom-gadget" to the right of the "depth-
- gadget".
-
- When the Select window shows the logical structure of objects, the View
- window is used for showing the physical structure of objects.
-
- The operation of View windows is part of the asynchronous design of REAL
- 3D. This means that they take full advantage of the Amiga multi-tasking
- environment by executing time consuming functions, like rendering, as a
- separate "task". This task will continue to run in the background, leaving
- the View free to respond to all user actions promptly.
-
- View Superbitmap
-
- Open superbitmap View, This means the window can be moved over a much
- larger "virtual" View using the scroll-bars at the bottom and right
- side. Objects can be created and modified, even rendered on any part of
- the superbitmap.
-
- View Borderless
-
- Open View covering the full screen. This has no visible borders and
- obscures the menu-strip. This window type is usually needed for rendering
- final images or animations where window borders are not desirable.
-
- View DBuffered
-
- Opens a double-buffered borderless View on a new screen. This enables
- wire-frame motion to be observed without seeing the intermediate drawing
- steps, so the image does not flicker. The new screen is always 4 color,
- 640 wide, maximum height and interlaced. This screen is
-
- - REFERENCE 1.12 -
-
- a special private screen and no other windows can be opened on it. By
- default the View projection type is perspective.
-
- RPL
-
- Open RPL Shell window for programming RPL words. This is an OS Shell
- window with support for all the editing, text history and clipboard
- hot-keys (<RAM>c and <RAM>v). It has no menu strip associated with it.
-
- RPL window is designed for interactive use. Henceforth each RPL window has
- its own environment where all RPL definitions are private to the window
- in question and cannot be accessed by other windows unless parent/child
- relationship is established using inheritance.
-
- All defined words, variables etc. also disappear when the window is
- closed. When more permanent definitions are desired, the Master
- environment can be used for that purpose and, when necessary, RPL windows
- can inherit Master's RPL context by executing the command Master INHERIT
- RPL words, variables etc. can be defined to the master's RPL environment
- by loading them as macros, sending them through the ARexx port or defining
- them in the "rpl-startup" file. The Master RPL environment is allocated
- when REAL 3D is started and it is used for executing macros, ARexx
- commands and requester formula evaluation.
-
- Tool
-
- Open Tool window for loading with tool icons. There are a number of pre-
- defined tool icons in the REAL 3D system, and these provide single-click
- short-cuts to selecting the most frequently used creation and modification
- functions. The user can also create his own icons using Tool/Create Icon.
- These icons can invoke any executable RPL file or RPL word.
-
- The purpose of Tool window is to provide the user with ability to expand
- and customize the user interface of the program to suit different kinds of
- projects. Tool windows have no separate RPL environment, so in order to
- bind icons to RPL words, the word must be defined in Master's RPL
- environment. If the icon is bind to a file, the RPL file must be found
- from the macros directory specified in Settings/Paths.
-
- Animation
-
- Open Animation window on its own private Hires screen.
-
- The animation window is used for controlling the animation system, for
- defining animation settings such as the number of frames to be used for
- rendering an animation and the name of the result file.
-
- Figure R1-4: Animation Window (PICTURE: R1-4)
-
- - REFERENCE 1.11 -
-
- Gadgets of Animation Window:
-
- Time
-
- The slider gadget and its associated numeric gadget provide the user with
- an interactive way of altering the global time. The affect of changing the
- time, with either the slider or by entering it numerically, depends on the
- state of the Play To/Jump To gadget.
-
- Play Controls
-
- These "video recorder" style controls have the following functions:
-
- |<... - Play backwards from current time to time 0.0
-
- ..>| - Play forwards to time 1.0
-
- |<- - Go to time 0.0
-
- ->| - Go to time 1.0
-
- <. - Single step one interval backwards
-
- .> - Single step one interval forwards
-
- CANCEL - Cancel all animation processing including rendering
-
- Play To/Jump To
-
- This gadget alters the way the Animation System reacts to changes to the
- time gadgets. If "Play To" is selected, then changing the time causes the
- animation to play from the current time to the new time. If "Jump To" is
- selected, then the display is just updated for the new time.
-
- Screens & Saved
-
- The list selector enables the one of the open REAL 3D screens to be
- selected for saving to an IFF file after each animation frame. The name
- can also be typed directly into the Saved text gadget. If an External
- screen has been opened, then it can be selected and will be saved using
- the file settings selected with Project/External_Screen/Settings.
-
- Resolution & Smpl (Samples)
-
- Resolution controls how many intervals time is divided into when it is
- evaluated from 0.0 to 1.0. Each step is evaluated internally with
- additional intervals set by Samples. Increasing Samples improves the
- quality of particle method evaluation. Samples is also used to determine
- the number of intervals over which to evaluate Motion Blur.
-
- Frame
-
- The current frame number. This value increase by one for every interval
- into which Time is divided by Resolution as the animation is saved.
- You can also use the gadget to move in time by entering the corresponding
- time value.
-
- Seconds
-
- The value in this field is only used by the Particle animation system to
- determine the amount of real time to evaluate particle movement properties
- over. This means that a particle with a velocity of 1.0 will travel 1.0
- ASCs in 1.0 real time seconds; the evaluation of spin is treated in a
- similar way. Increasing "Seconds" increases the amount of motion for each
- particle during the whole animation.
-
- Format
-
- This is an index format string which is used to format the current Frame
- number before appending it to the end of Screen file text, Individual
- Views, which are also handles to files, use the formatted index for their
- file saving.
-
- Save
-
- If set, then the selected screen is saved to file and Frame is
- incremented, after rendering of the current frame is completed.
-
- Screen File
-
- The name and path for the screen image files saved by the Animation
- system.
-
- - REFERENCE 1.14 -
-
- Frame Cmd
-
- This can contain RPL text which is interpreted by the "Master" RPL
- environment every time Frame is incremented. By using the RPL word
- "SYSTEM", commands can be passed to the CLI to control, for example, a
- single-frame video recorder system. Or alternatively, the frame command
- can for example convert IFF images the renderer produces to the JPEG
- format.
-
- Palette
-
- Open Palette window. This is opened on its own private HAM screen. The
- Palette is used to control the R,G,B values of the current color and the
- 16 register color values. The current color is used whenever REAL 3D
- requires a color value for a function e.g. Modify/Properties/Color.
-
- Figure R1-5: Palette Window (PICTURE: R1-15)
-
- The register colors give the user fast access to 16 different color
- definitions. Selecting one of the register color buttons makes the current
- color the same as the current value of the register color. The value of
- the register color is then changed using either the sliders or selecting
- from the color spectrum with the left mouse button. Holding the left
- button down while moving over the color spectrum changes the current color
- and the slider values continuously. There is no need to confirm these
- changes. The effects take place when the "OK" gadget is pressed. It is
- also necessary to select the settings required BEFORE using a function
- which uses the current color. If a Palette window is not currently open,
- then the last setting for the current color will be used.
-
- Measuring
-
- This opens the Measuring system window. The Measuring system can be used
- for replacing the mouse when accurate input is needed. It also allows the
- user to define coordinates using natural units, such as meters and feet,
- instead of just plain absolute space coordinates.
-
- Figure R1-6: Measuring Window (PICTURE)
-
- - REFERENCE 1.15 -
-
- Measuring window gadgets:
-
- X, Y, Z
-
- These gadgets show the current position of the mouse in current units. The
- user can also enter coordinates through these gadgets, in which case the
- effect is the same as if the user moved the mouse to the corresponding
- point in View window. Formula evaluation is also supported, making it
- possible to enter formulas instead of coordinate values.
-
- The purpose of these gadgets depends on the measuring type used. If
- "Normal" method is used, these fields define 3D coordinate values relative
- to input-plane/absolute space and origin/hotpoint depending on the state
- of other gadgets on the window. If "Polar" is used, X and Y fields define
- the direction (horizontal and vertical angle) and Z field is used for
- distance. Polar coordinates can also be relative to hot-point/origin and
- input-plane/absolute space. The direction is always defined in degrees.
-
- N
-
- The purpose of this gadget varies from one function to another. It can be
- used for defining angles for sector primitives, depths for primitives etc.
-
- Absolute/I-plane (Input-plane)
-
- This radio button defines whether the coordinates are relative to the
- Input Plane or Absolute Space.
-
- Normal/Polar
-
- This radio button defines whether to use normal 3D coordinate system or
- polar (angle&radius) coordinates.
-
- Origin/Hot-point
-
- This radio button defines whether to use coordinates relative to origin
- of absolute space or to hot-point.
-
- Unit
-
- The cycle gadget defines the unit to be used. The absolute space units
- corresponds to meters. Possible choices are:
-
- Symbol Description Abs. Space Units
-
- m meters 1.0
- mm millimeters 0.0001
- cm centimeters 0.01
- in inches 0.02548
- ft feet 0.3048
-
- Screen
-
- This opens a small window which enables control of the public screens used
- by REAL 3D. It is opened automatically when a new screen is created to
- provide a "handle" to the REAL 3D menus, until other windows have been
- opened.
-
- Gadgets of the screen window:
-
- Default
-
- Make active screen the default public screen.
-
- Jump
-
- Jump to next public screen. The control window will follow.
-
- Close
-
- Close all REAL 3D windows on the current screen then attempt to close the
- screen. If other windows prevent the closure, then a warning requester
- will be opened
-
- Hijack
-
- When enabled, windows and requesters opened for public screens will be
- hijacked and opened on the default public screen. This allows other
- applications which use public screens to be integrated into the REAL 3D
- system. One possibility for this is to integrate a text editor for
- creating and editing the text for RPL.
-
- - REFERENCE 1.16 -
-
- Pop-to-front
-
- When windows and requesters are opened on the default public screen, it
- will be brought to the front.
-
- Close
-
- Close the currenCy selected window. Some windows, for example a
- borderless-View, do not have a close gadget. This function enables all
- windows to be closed.
-
- * No Gadgets
-
- This function removes all the gadgets for controlling the View window to
- leave a window with a narrow surrounding border. This window cannot be
- moved or re-sized until this function is selected again.
-
- Environment/
-
- "Environment consists of the following data sections:
- - screens
- - windows (including Measuring system)
- - global settings:
- - frame buffer library name
- - save format for frame buffer (tga, iff, ...)
- - RPL initial configuration
- - current tool name for modify system
- - current register and RGB color
- - operation level
- - settings for modify subsystem
- - default directory paths for projects, objects, textures etc.
- - aspect ratio
- - hot-point
- - undo settings
- - load/save sections
- - sections
- - vector/float format strings
- - file name for current macro
- - minimum dragging time
- - default settings for fractal generators
-
- Open Screen
-
- Open new REAL 3D screen using Screen-settings requester.
-
- Make Def.Pub.
-
- Make currenCy selected screen the default public screen.
-
- Close Screen
-
- Close selected REAL 3D screen.
-
- Close Current
-
- Close any windows currently open on active screen and then attempt to
- close the screen. If other programs have opened windows on the REAL 3D
- screen, then the screen cannot be closed and the user will be warned.
-
- Insert
-
- Load a new environment definition from the file specified. This will
- create a set of windows and screens in addition to the existing ones.
-
- Save
-
- Save the complete environment definition to the file specified.
-
- Replace
-
- Delete existing environment definition before loading the specified
- environment file.
-
- Save Screen
-
- Open a File Requester and then save the active-screen as the specified
- IFF file.
-
- - REFERENCE 1.17 -
-
- Screen Palette
-
- Figure R1-7: Screen Palette Requester (PICTURE: R1-7)
-
- Open a requester enabling the active screen colors to be changed. The
- screen register color to modify is selected from the color spectrum,
- then it can be adjusted using the RGB sliders. Two pre-defined palette
- definitions can be loaded
-
- by selecting either of the two button-gadgets. The "COLOR SCALE"
- definition is used with Render Settings/"Color Shading". Screen palettes
- are saved as part of the screens data section.
-
- External Screen/
-
- These functions enable a library for controlling an External screen, like
- a frame buffer, to be used.
-
- Open
-
- Open an External screen with its specified External screen library.
-
- Close
-
- Close External screen and its library.
-
- Set Modes
-
- This function allows settings of an External screen to be modified. Not
- all libraries need this function, and so will not produce a requester.
-
- Settings
-
- Opens External screen requester allowing the user to select External
- screen library and file format.
-
- Figure R1-8: External Screen Settings Requester (PICTURE: R1-8)
-
- Gadgets of the External screen requester:
-
- Library
- Name of External screen library.
-
- IFF24
- IFF 24 file format used.
-
- TARGA
- Targa file format used.
-
- TARGA+A-
- Targa file format with alpha-information used for saving.
-
- - REFERENCE 1.18 -
-
- CUSTOM
-
- External screen's own format.
-
- Save
-
- Save image from External screen using format specified by settings.
-
- Exit Real
-
- Close all REAL 3D windows and screens and return to WB. If other programs
- have opened windows or requesters on any of REAL 3D's public screens, then
- the program will warn the user and leave the screens open.
-
- 1.2 CREATE
-
- Creating the various primitive and compound-objects is carried out by
- selecting the function and then supplying the appropriate data
- coordinates. This is usually carried out with the mouse. The <LMB> defines
- the View in which the operation will be carried out, selects the first
- coordinate and starts the operation. It also defines consecutive
- coordinates. The <RMB> completes a phase of the function. This may either
- move onto the next phase, complete the creation, or cancel the whole
- function. The first component of each primitive is ALWAYS created on the
- input plane. Those components with depth are then extruded perpendicular
- to the input plane. The direction of extrusion is determined using the
- Right Hand Rule.
-
- All 2D primitives, such as rectangle, circle and polygon, contain a small
- stick called as "dvect", which describes the volume defined by the
- primitive. This information is needed when object is used in Boolean
- operations. 2D primitives divide the space to two different parts and the
- dvect describes which side is the inside of the primitive. This means that
- REAL 3D can handle infinite solids and they don't have to be closed (some
- other solid modelling packages require that the solid must be closed, so
- it is not possible to get inside it without passing through surfaces used
- for defining it).
-
- Visibles/
-
- This sub-menu contains all the creation functions for the basic visible
- primitives.
-
- Polygon
-
- PRIMITIVE: polygon
- Create polygonal plane.
- DEFINE: three or more points on a polygon.
-
- Terminating the function before creating 3rd point cancels the creation.
-
- Polyhedron
-
- PRIMITIVE: polyhedron
- Create polygonal prism.
- DEFINE: polygonal cross-section.
-
- The cross-section is extruded to defined depth.
-
- Polymid
-
- PRIMITIVE: polymid
- Create polygonal based pyramid.
- DEFINE: polygonal base and apex.
-
- Cut polymid
-
- PRIMITIVE: cut-polymid
- Create polygonal based pyramid with truncated apex.
-
- Figure R1-9: Polygon-based Visibles (PICTURE: R1-9)
-
- - REFERENCE 1.19 -
-
- DEFINE: polygonal base, center of truncating surface and radial size of
- truncating surface.
-
- Figure R1-10: Rectangle-based Visibles (PICTURE: R1-10)
-
- Rectangle
-
- PRIMITIVE: rectangle
- Create rectangular plane.
- DEFINE: two coordinates of diagonally opposite corners of rectangle.
-
- Cube
-
- PRIMITIVE: cube
- Create rectangular prism.
- DEFINE: rectangular cross-section. The cross-section is defined as for
- rectangle. On completion, the rectangle is extruded to depth.
-
- Pyramid
-
- PRIMITIVE: pyramid
- Create rectangular based prism.
- DEFINE: rectangular base and apex.
-
- Cut pyramid
-
- PRIMITIVE: cut-pyramid
- Create rectangular based prism with truncated apex.
- DEFINE: two separate rectangles. The two rectangles form the two parallel
- surfaces with additional planes created automatically for the sides.
-
-
-
- END OF PART 4
-
-
-
-
-
-
-